Exemplo n.º 1
0
 def application_generate_msg(self):
     # Generates an application message and puts it into the end of the
     # outbox.
     # assert self.nextHop is not None, 'No next hop found'
     # Simulating the application message as one optical data message.
     msg = MG.create_optical_datamsg(self.addr, 1, self.basicPayload,
                                     self.clock.read())
     if self.state is UOARState.CLUSTER_MEMBER:
         end_msg = MG.create_optical_datamsg(self.addr, self.nextHop, msg,
                                             self.clock.read())
     else:
         end_msg = MG.create_acoustic_datamsg(self.addr, self.nextHop, msg,
                                              self.clock.read())
     self.outbox.append([end_msg, 0])
Exemplo n.º 2
0
    def handle_message(self, msg):
        # Handles the received messages acording to their types.
        msgType = msg.flags & 0x0f  # first half is the type

        if msgType is UOARTypes.COMMON_DATA:
            if self.verbose:
                print('Handling data message from node ' + str(msg.src))

            innerMsg = msg.payload
            innerMsg.ttl -= 1
            if innerMsg.dst is not self.addr:
                if innerMsg.ttl is not 0:
                    if self.state is UOARState.CLUSTER_MEMBER:
                        msg = MG.create_optical_datamsg(
                            self.addr, self.nextHop, innerMsg,
                            self.clock.read())
                    else:
                        msg = MG.create_acoustic_datamsg(
                            self.addr, self.nextHop, innerMsg,
                            self.clock.read())
                    self.outbox.append([msg, 0])
                else:
                    if self.verbose:
                        print('Message droped (TTL reached 0)')
            self.recvdMsgsCounter += 1
            if self.isSink is True:
                # Hops statistics
                corrCoeff = (self.recvdMsgsCounter - 1) / self.recvdMsgsCounter
                numHops = BASIC_TTL - innerMsg.ttl
                if numHops > self.maxNumHops:
                    self.maxNumHops = numHops
                self.avgNumHops *= corrCoeff
                self.avgNumHops += (numHops / self.recvdMsgsCounter)
                # Time statistics
                time = self.clock.read() - innerMsg.ctime
                if self.verbose:
                    print('Received (time: ' + str(time) + ')')
                if time > self.maxTimeSpent:
                    self.maxTimeSpent = time
                self.avgTimeSpent *= corrCoeff
                self.avgTimeSpent += (time / self.recvdMsgsCounter)

        elif msgType is UOARTypes.INFO_ANNOUN:
            if self.verbose:
                print('Handling info message from node ' + str(msg.src))

            self.numReachableNodes += 1
            nodePosition = msg.payload[0]
            nodeState = msg.payload[1]
            nodeHops = msg.payload[2]
            distFromNode = Tools.distance(self.position, nodePosition)
            # Adding in lists
            if nodeState is UOARState.CLUSTER_HEAD:
                self.cheadList[msg.src] = nodeHops is not INFINITY
            if distFromNode <= OM.maxrange:
                self.oneighbors[msg.src] = nodePosition
                if nodeState is UOARState.CLUSTER_MEMBER and \
                   msg.src not in self.cmemberList:
                    self.cmemberList.append(msg.src)
            updtFactor = (self.numReachableNodes - 1) / self.numReachableNodes
            self.avgDistance = self.avgDistance * updtFactor
            self.avgDistance += (distFromNode / self.numReachableNodes)
            if distFromNode > self.greaterDistance:
                self.greaterDistance = distFromNode

            if self.state is UOARState.INITIAL and not self.isSink:
                # If it is not in a cluster and some neighbor is already
                # member or a head, join it. It's preferable to join as
                # a member than as a head.
                if distFromNode <= OM.maxrange:
                    if nodeState is not UOARState.INITIAL:
                        currDist = INFINITY
                        if self.nextHop in self.oneighbors:
                            nextPos = self.oneighbors[self.nextHop]
                            currDist = Tools.distance(self.position, nextPos)
                        if distFromNode < currDist:
                            self.nextHop = msg.src
                            self.hopsToSink = INFINITY

                else:
                    if nodeState is UOARState.CLUSTER_HEAD:
                        if self.hopsToSink is INFINITY:
                            if self.nextHop is None:
                                self.nextHop = msg.src
                                self.hopsToSink = nodeHops + 1
                        else:
                            if (nodeHops + 1) < self.hopsToSink:
                                self.nextHop = msg.src
                                self.hopsToSink = nodeHops + 1

            if (self.state is not UOARState.INITIAL and \
               self.status is not UOARStatus.DISCOVERING) and \
               nodeState is UOARState.INITIAL:
                # When a node enters in the network and needs information.
                # Routing control messages have higher priority than data
                # messages.
                msg = MG.create_iamsg(self.addr, self.position, self.state,
                                      self.hopsToSink)
                # Insert the message in que outbox or updates the next ot
                # be sent.
                if len(self.outbox) is not 0:
                    firstMsgType = self.outbox[0][0].flags & 0x0f
                    if firstMsgType is not UOARTypes.INFO_ANNOUN:
                        self.outbox.insert(0, [msg, 0])
                    else:
                        self.outbox[0] = [msg, 0]
                else:
                    self.outbox.insert(0, [msg, 0])

        elif msgType is UOARTypes.SCORE_ANNOUN or \
             msgType is UOARTypes.REP_SCORE:
            if self.verbose:
                print('Handling score message from node ' + str(msg.src))

            nodeScore = msg.payload[0]
            if msg.src in self.oneighbors and \
               (self.status is UOARStatus.ANNOUNCING or \
               self.status is UOARStatus.DISCOVERING or \
               self.status is UOARStatus.UPDATING):
                # Cluster heads are nodes with the highest score amoung its
                # neighbors (in case of a tie, the node with lowest addr wins)
                if (self.highestScore[0] < nodeScore) or \
                   (self.highestScore[0] == nodeScore and \
                    self.highestScore[1] > msg.src):
                    self.highestScore = [nodeScore, msg.src]

        elif msgType is UOARTypes.CLUSTER_ANNOUN:
            if self.verbose:
                print('Handling cluster message from node ' + str(msg.src))

            nodeIsHead = msg.payload[0]
            if nodeIsHead:
                # A cluster head node will send its own address in the cluster
                # announcement payload
                if msg.src not in self.cheadList:
                    if self.status is UOARStatus.ELECTING or \
                       self.status is UOARStatus.ANNOUNCING:
                        self.cheadList[msg.src] = False
                    else:
                        self.cheadList[msg.src] = True

                if msg.src in self.cmemberList:
                    self.cmemberList.remove(msg.src)
            else:
                if msg.src in self.oneighbors and \
                   msg.src not in self.cmemberList:
                    self.cmemberList.append(msg.src)
                    if msg.src in self.cheadList:
                        del self.cheadList[msg.src]

            if msg.src in self.oneighbors and \
               self.status is UOARStatus.DISCOVERING:
                self.nextHop = msg.src

        elif msgType is UOARTypes.ROUTE_ANNOUN:
            if self.verbose:
                print('Handling route message from node ' + str(msg.src))
            nodeIsHead = msg.payload[0]
            nodeNextHop = msg.payload[1]
            nodeHops = msg.payload[2] + 1
            nodePosition = msg.payload[3]
            if self.state is UOARState.CLUSTER_HEAD:
                if nodeIsHead:
                    dist = Tools.distance(self.position, nodePosition)
                    self.cheadList[msg.src] = True
                    if self.hopsToSink > nodeHops or \
                       (self.hopsToSink == nodeHops and \
                       dist < self.nextHopDist):
                        self.hopsToSink = nodeHops
                        self.nextHop = msg.src
                        self.nextHopDist = dist

                elif self.isSink is False:
                    if nodeHops < self.minHopsToSink:
                        self.minHopsToSink = nodeHops
                        self.memberAlternative = msg.src

                    if self.nextHop is not None and \
                       nodeNextHop is not self.addr:
                        if msg.src in self.oneighbors and \
                           nodeHops <= (self.hopsToSink + 1):
                            # better be a member than a head
                            # print('Node ' + str(self.addr) + ' was member 2')
                            # print(nodeIsHead)
                            # print(nodeNextHop)
                            # print(nodeHops)
                            # print(nodePosition)
                            # print(self.hopsToSink + 1)
                            self.state = UOARState.CLUSTER_MEMBER
                            self.nextHop = msg.src
                            self.hopsToSink = nodeHops
                            newMsg = MG.create_camsg(self.addr, False,
                                                     self.position)
                            self.outbox.insert(0, [newMsg, 0])

            if (self.status is UOARStatus.WAITING or \
               self.status is UOARStatus.ELECTING) and \
               self.nextHop is msg.src:
                # For members
                if nodeHops < self.minHopsToSink:
                    self.minHopsToSink = nodeHops
                    newMsg = MG.create_ramsg(self.addr, False, self.nextHop,
                                             nodeHops, self.position)
                    self.outbox.insert(0, [newMsg, 0])
                self.stopWaiting = True

        elif msgType is UOARTypes.REQ_SCORE:
            if self.verbose:
                print('Handling req score msg from ' + str(msg.src))

            if msg.src in self.oneighbors:
                # self.score = self.calculate_score()
                # newMsg = MG.create_rpsmsg(self.addr, msg.src, self.score)
                score = self.calculate_score()
                newMsg = MG.create_rpsmsg(self.addr, msg.src, score)
                if len(self.outbox) is not 0:
                    firstMsgType = self.outbox[0].flags & 0x0f
                    if firstMsgType is not UOARTypes.REP_SCORE:
                        self.outbox.insert(0, [newMsg, 0])
                    else:
                        self.outbox[0] = [newMsg, 0]
                else:
                    self.outbox.append([newMsg, 0])

        elif msgType is UOARTypes.UPDATE_INFO:
            if self.verbose:
                print('Handling update info msg from ' + str(msg.src))

            newHead = msg.payload[0]
            newNextHop = msg.payload[1]
            if newHead is self.addr:
                # Must be a head now
                self.state = UOARState.CLUSTER_HEAD
                self.nextHop = newNextHop
            else:
                if self.nextHop is msg.src or newHead in self.oneighbors:
                    # Must update which node is the next hop
                    ##################################################
                    ## Might be a problem is new head is out of range
                    ##################################################
                    self.nextHop = newHead
                self.cheadList[newHead] = True

            if newHead in self.oneighbors:
                self.cmemberList.remove(msg.payload[0])

            if msg.src in self.oneighbors:
                self.cmemberList.append(msg.src)

            del self.cheadList[msg.src]

            if self.verbose:
                print(self.cheadList)
                print(self.cmemberList)

        elif msgType is UOARTypes.REQ_RINFO:
            if self.verbose:
                print('Handling route info request msg from ' + str(msg.src))

            if msg.src is not self.nextHop and \
               msg.payload[0] is not self.nextHop:
                # Only replies if the requester is not its own next hop and
                # they don't share the same next hop. (-_- can't help)

                if msg.src in self.oneighbors:
                    newMsg = MG.create_optical_rprmsg(self.addr, msg.src,
                                                      self.nextHop,
                                                      self.hopsToSink)
                else:
                    newMsg = MG.create_acoustic_rprmsg(self.addr, msg.src,
                                                       self.nextHop,
                                                       self.hopsToSink)
                self.outbox.insert(0, [newMsg, 0])

        elif msgType is UOARTypes.REP_RINFO:
            if self.verbose:
                print('Handling route info reply from ' + str(msg.src))

            if self.status is UOARStatus.RECOVERING:
                nodeNextHop = msg.payload[0]
                nodeHopsToSink = msg.payload[1]
                replier = msg.src
                if replier in self.oneighbors:
                    self.nextHop = msg.src
                    self.hopsToSink = INFINITY
                    print('Node ' + str(self.addr) + ' was member 3')
                    self.state = UOARState.CLUSTER_MEMBER

                if self.state is UOARState.CLUSTER_HEAD and \
                   self.hopsToSink >= nodeHopsToSink:
                    self.nextHop = msg.src
                    self.hopsToSink = nodeHopsToSink + 1

        elif msgType is UOARTypes.ACK:
            if self.verbose:
                print('Handling ACK from node ' + str(msg.src))

            if self.waitingACK:
                self.outbox.pop(0)
                self.waitingACK = False
                if self.msgsLostCount is not 0:
                    self.msgsLostCount = 0
            else:
                if self.verbose:
                    print('error: unknown ack received')

        else:
            if self.verbose:
                print('unknown message type')