Exemple #1
0
class Synchronizer():

    def __init__(self, fog):

        self.multicast_address = ('239.255.4.3', 1234)
        self.sock = self.create_socket('239.255.4.3', 1234)
        self.fog = fog
        self.factory = Factory()

    def create_socket(self, multicast_ip, port):
        """
        Creates a socket, sets the necessary options on it, then binds it. The socket is then returned for use.
        """

        local_ip = socket.gethostbyname(socket.gethostname())

        # create a UDP socket
        my_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        # allow reuse of addresses
        my_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # set multicast interface to local_ip
        my_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))

        # Set multicast time-to-live to 2...should keep our multicast packets from escaping the local network
        my_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)

        # Construct a membership request...tells router what multicast group we want to subscribe to
        membership_request = socket.inet_aton(multicast_ip) + socket.inet_aton(local_ip)

        # Send add membership request to socket
        # See http://www.tldp.org/HOWTO/Multicast-HOWTO-6.html for explanation of sockopts
        my_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, membership_request)

        my_socket.bind(('', port))
        
        return my_socket

    def senddata(self, data, address):

        sent = self.sock.sendto(data, address)
        if sent == 0:
            raise RuntimeError('socket connection broken')

        return sent

    def recvdata(self):
        datagram = ''
        try:
            while True:
                datagram, address = self.sock.recvfrom(1024)
                if address == '':
                    raise RuntimeError('socket connection broken')

                if address[0] == self.fog.ip: #myself
                    continue

                response = self.factory.parse_response(datagram)

                # validar pacote. verificar se eh ACK
                if response.messagetype == 'ack':
                    self.fog.ack(address[0])

                # validar pacote. verificar se eh k.a
                elif response.messagetype == 'keepalive':

                    # valida se deve inserir novo nodo ou atualizar
                    if self.fog.containsResource(ip=address[0]):

                        # utiliza epoch recebida para validar se houve alteracoes
                        if self.fog.epochHasChanged(ip=address[0], epoch=response.epoch):

                            # se houve alteracoes(atualizacao de recurso). realiza requisicao coap
                            client = HelperClient(server=(address[0], 5683))
                            responseCoap = client.get('/.well-known/core')

                            # utiliza epoca do recurso que foi recebido por broadcast
                            self.fog.updateResource(ip=responseCoap.source[0], resources=responseCoap.payload, epoch=response.epoch)

                    # utiliza epoca do recurso que foi recebido por broadcast
                    # se houve alteracoes(inclusao de novo nodo). realiza requisicao coap
                    else:
                        client = HelperClient(server=(address[0], 5683))

                        # tratar timeout
                        responseCoap = client.get('/.well-known/core')
                        if responseCoap == None:
                            pass
                        self.fog.insertResource(ip=responseCoap.source[0], resources=responseCoap.payload, epoch=response.epoch)

                    # responde ACK para qm enviou o ka.
                    datagram = self.factory.build_request(epoch=self.fog.epoch, seq_number=self.fog.seq_number, message_type='ack')
                    self.senddata(datagram, address)

        except socket.timeout as error:
            print 'timeout'
            print error.message

        except Exception as error:
            print error.message
            # self.sock.close()

    def observer(self):
        # busca em coapserver os proprios recursos
        # frequentemente realizar esse request para se monitorar.
        # caso haja alteracoes nos recursos, incrementar epoca        

        print 'observer'
        client = HelperClient(server=(self.fog.ip, 5683))
        responseCoap = client.get('/.well-known/core')

        if responseCoap.payload == None:
            responseCoap.payload = []

        # atualiza epoca se estiver diferente
        self.fog.checkMyResources(responseCoap.payload)
        self.fog.resources = responseCoap.payload

        time.sleep(10)
        return self.observer()

    def keepalive(self):
        print 'send keepalive'
        datagram = self.factory.build_request(epoch=self.fog.epoch, seq_number=self.fog.seq_number, message_type='keepalive')

        self.fog.sendingKeepAlive()
        self.senddata(datagram, self.multicast_address)
        time.sleep(30)
        self.fog.removeInactiveNodes()

        return self.keepalive()

    def worker(self):

        worker_server_address = (socket.gethostbyname(socket.gethostname()), 5001)
        sock_worker = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock_worker.bind(worker_server_address)

        print 'sync worker running on address: ' + str(worker_server_address[0]) + ' and port ' + str(worker_server_address[1])

        while True:
            try:
                data, client_address = sock_worker.recvfrom(1024)
                operation = data[0]

                if operation == 'p':
                    sock_worker.sendto(self.fog.printResources(), client_address)  
                    continue
                else:
                    sock_worker.sendto('Missing params', client_address)
                    continue

            except socket.timeout:
                print 'TIMEOUT'
                continue