def connect(self, factory, name, port, connectionType="RAW"): name = str( name) # force to a string in case we're accidentally given an addr try: pAddr = PlaygroundAddress.FromString(name) except: pAddr = None self.__trueConnectD = defer.Deferred() trueConnect = lambda address: self.__trueConnectD.callback( self.__clientBase.connect(factory, address, port, connectionType)) if not pAddr: if not isinstance(self.__n2pServerAddr, PlaygroundAddress): try: self.__n2pServerAddr = PlaygroundAddress.FromString( self.__n2pServerAddr) except: Timer.callLater( .1, lambda: self.__trueConnectD.errback( Exception( "Could not connect to resolver. Bad address %s" % self.__n2pServerAddr))) return self.__trueConnectD srcport, self.__resolver = self.__clientBase.connect( N2PClient(), self.__n2pServerAddr, N2PServer.DEFAULT_SERVING_PORT, "SECURE_STREAM") d = self.__resolver.waitForConnection() d.addCallback( lambda result: self.__resolverConnected(name, trueConnect)) d.addErrback(self.__resolverConnectFailed) else: Timer.callLater(.1, lambda: trueConnect(pAddr)) return self.__trueConnectD
def __checkConnectionState(self): if self.__connected == CONNECTED and self.__state == DATA: self.__processBuffer() elif self.__connected == CONNECTED and self.__state == FIN: self.transport.loseConnection() self.getHigherProtocol().connectionLost("Sent FIN, Timed out") else: Timer.callLater(0.05, lambda:self.__checkConnectionState())
def retransmit(self, seqNum, sMessage): if not self.state == "CLOSED": if seqNum in [x[0] for x in self.unacknowledgedSent]: i = [x[0] for x in self.unacknowledgedSent].index(seqNum) self.unacknowledgedSent[i][2] = Timer.callLater(self.timeout, self.retransmit, seqNum, sMessage) logger.debug("RIP--Retransmitting packet %d", seqNum) self.lowerTransport().write(sMessage)
def __ptclMessageHandler(self, protocol, msg): ##print "I have received a message from the network, checking it's sanity:" msgObj = msg.data() # first compare the hashes. sane = self.sanity(msg) if sane: ##print "packet is sane" pass else: ##print "packet is insane" return 0 # Bifurcate the code flow based on the message type # handleConnectionMessages takes care of SYN/SYNACK/ACK/FIN/FINACK # handleDataAck handles the ACKs sent to acknowledge successful data delivery # handleDataRcvMessage handles the data messages if msgObj.MessageType == "SYN": #DO This ##print "I got a SYN \n" self.__handleConnectionMessages(1, msgObj) # TO DO check for current state. elif msgObj.MessageType == "SYNACK": #Do this ##print "I got a SYNACK \n" self.__handleConnectionMessages(2, msgObj) elif msgObj.MessageType == "ACK": #DO This ##print "I got an ACK \n" if (self.__connected): ##print "For connected connection" self.__handleAck(msgObj) else: ##print "For unconnected connection" self.__handleConnectionMessages(3, msgObj) elif msgObj.MessageType == "DATA": #Fixed : would allow a DATA packet to be processed directly without a connection ##print "I got DATA \n" self.__data_timer = Timer.OneshotTimer(lambda: self.checkData()) if (self.__connected == 1): self.__handleDataRcvMessage(msgObj) else: pass ##print "No connection present aborting" elif msgObj.MessageType == "FIN": #Do This ##print "I got a FIN \n" self.__handleConnectionMessages(6, msgObj) elif msgObj.MessageType == "FINACK": #Do this ##print "I got a FINACK" self.__handleConnectionMessages(8, msgObj) else: #TODO - Do nothing - log it - ##print something to screee/log return 0
def write(self, serialized_msg_from_top): #print "write" self.__pushToList(serialized_msg_from_top) logger.info("Message put in buffer, checking connection state") if (self.__connected == NOTCONNECTED): # No existing connection initiating handshake logger.info("PSST Handshake: Starting handshake") self.__initiateHandshake() Timer.callLater(0.05, lambda:self.__checkConnectionState()) elif (self.__connected == HANDSHAKE): # Handshake still not complete, buffer the messages logger.info("PSST Handshake: Handshake not complete") Timer.callLater(0.05, lambda:self.__checkConnectionState()) elif (self.__connected == CONNECTED): logger.info("PSST Handshake: Hanshake now complete, ready to send buffered messages") self.__processBuffer() else: logger.debug("PSST Handshake: Unknown connected state reached")
def writeSignedMessage(self, rMessage, shouldRetransmit): if self.idleTimeout: self.resetTimeout() else: self.initTimeout() rMessage.sequence_number = self.nextSequenceNumber rMessage.sessionID = self.sessionID rMessage.signature = "" unsignedMessage = rMessage.__serialize__() sig = self.sign(unsignedMessage) rMessage.signature = sig sMessage = rMessage.__serialize__() if len(rMessage.data) == 0: if not rMessage.acknowledgement_flag or rMessage.sequence_number_notification_flag: self.nextSequenceNumber = self.nextSequenceNumber + 1 else: self.nextSequenceNumber = self.nextSequenceNumber + len(rMessage.data) if len(self.unacknowledgedSent) >= self.maxSent and not rMessage.acknowledgement_flag: self.sendOverflow.append((self.nextSequenceNumber, sMessage, shouldRetransmit)) else: self.lowerTransport().write(sMessage) if shouldRetransmit: callNum = Timer.callLater(self.timeout, self.retransmit, self.nextSequenceNumber, sMessage) self.unacknowledgedSent.append([self.nextSequenceNumber, sMessage, callNum])
def __handleDataRcvMessage(self, msgObj): if (self.__connected == 0): ##print "Connection Not Established Yet" return self.__state = 4 self.__exp_backoff = 0.05 # Fixed : If server responds, it will not go through connection set up again and hence last_contig needs to be set to # the seq number of the first data packet by server - 1 so that the system does not break if self.__connected == 1 and self.__last_contig == 0: self.__last_contig = msgObj.MessageSeq - 1 ##print "I have received Data, with serial number: ",msgObj.MessageSeq #if msgObj.MessageSeq <= self.__last_contig or msgObj.MessageSeq == 0: if msgObj.MessageSeq <= self.__curr_ackSeq or msgObj.MessageSeq == 0: ##print "Message is stale or has sequence 0, discard" return pushed = self.push_to_rcv_window(msgObj.MessageSeq, msgObj) if (pushed): pass ##print "Message pushed to window successfully" else: pass ##print "Pushing to window unsuccessful - either msgseq too big or too small" #self.__curr_ackSeq = msgObj.MessageSeq # Check if the packet received is the next contiguous packet, if it is check if it # completes a sequence, send the maximum number of contiguous packets up the layer # and slide the data rcv window logger.info("Harsh: " + str(self._addr) + " Got data on the receiver with sequence number: " + str(msgObj.MessageSeq) + " expected contiguous sequence number is :" + str(self.__curr_ackSeq + 1)) #str(self.__last_contig+1)) #if (msgObj.MessageSeq == self.__last_contig+1): if (msgObj.MessageSeq == self.__curr_ackSeq + 1): #logger.info("Harsh: "+str(self._addr)+" Got data on the receiver with contiguous sequence number: "+str(msgObj.MessageSeq)) # TODO: Find a way to reset the timer. ##print "Got the next contig packet resetting the timer" #print "Cancelled hb_timer" self.__hb_timer.cancel() #print "Restarted hb_timer" self.__hb_timer = Timer.OneshotTimer(lambda: self.checkData()) self.__hb_timer.run(0.05) for seq in range(0, RCVWINDOW): if self.__rcvWindow[seq][0] == -1: # reached end of max contiguous list present break # set last contig as the maximum contig seq number present in rcv window and acknowledge that packet #self.__last_contig = self.__rcvWindow[seq-1][0] #self.__curr_ackSeq = self.__last_contig self.__curr_ackSeq = self.__rcvWindow[seq - 1][0] # print "Sending an ack with seq number: ",self.__currSeq, "and ack-ing max contiguously received seq number: ",self.__last_contig self.__handleConnectionMessages(7, msgObj) #Do window sliding for i in range(0, seq): rawData = self.__rcvWindow[i][1].Data ##print "Now Passing Data up the layer" self.getHigherProtocol().dataReceived(rawData) self.slideRcvWindow(i + 1)
def transmitOverflow(self): self.sendOverflow.sort() while len(self.unacknowledgedSent) < self.maxSent and len(self.sendOverflow) > 0: seqNum, sMessage, shouldRetransmit = self.sendOverflow.pop() self.lowerTransport().write(sMessage) if shouldRetransmit: callNum = Timer.callLater(self.timeout, self.retransmit, seqNum, sMessage) self.unacknowledgedSent.append([seqNum, sMessage, callNum])
def start(self, clientBase, args): self.clientBase = clientBase result, msg = True, "" if "start_server" in args: mobileCodeServer = playground.network.client.sampleservers.ClientMobileCodeServer( ) result = clientBase.listen(mobileCodeServer, 100) if result == True: self.serving = True else: msg = "Could not start server" if "start_client" in args: print "start client" computePi = ComputePi( clientBase, playground.network.client.sampleservers.MobileCodeClient()) Timer.callLater(0, lambda: computePi.start(10000000)) self.client = computePi if not self.serving and not self.client: result, msg = False, "computePi requires either 'start_server', 'start_client', or both" return result, msg
def checkData(self): ###print "Inside checkData that means I did not get a new Data Message" ###print "Re sending ack for last contiguous packet" if (self.__finhandshake == 1): ##print "Connection Ending no need to send handshake" return None self.__exp_backoff *= 2 if self.__exp_backoff >= 10: self.__exp_backoff = 10 self.__handleConnectionMessages(7) self.__hb_timer = Timer.OneshotTimer(lambda: self.checkData()) self.__hb_timer.run(self.__exp_backoff)
def checkWindow(self): if self.__dataList != [] or self.__window != []: #if self.__fin_timer: # self.__fin_timer.cancel() self.__fin_timer = Timer.OneshotTimer(lambda: self.checkWindow()) self.__fin_timer.run(0.1) else: if self.__connected == 1: if self.__finhandshake == 0: self.__finhandshake = 1 self.__handleConnectionMessages(5) else: pass else: pass
def __handleAck(self, msgObj): self.__session_timer.cancel() self.__session_timer = Timer.OneshotTimer(lambda: self.checkSession()) self.__session_timer.run(35) if self.__window == []: ##print "The window is empty, probably keep alive ACKs" pass next_expected = self.top('Win') if msgObj.AckSeq < next_expected - 1: ##print "Delayed/Duplicate ACK, discarding" return ##print "I have received ACK for the data I sent, ack :",msgObj.AckSeq # Move the window forward if the seq number being ACK'd is the first # or higher in the list.Accodingly move the dataQueue forward too # If the ack'd packet is less than the first packet in the window check # if the ACK'd sequence is adjacent to the sequence at Window[0]. If yes # that means you have to send Window[0] again. # Else just discard the ACK as it is a delayed ACK. if (self.__window != [] and msgObj.AckSeq >= next_expected): logger.info( "Harsh: " + str(self._addr) + " Got the ACK on the sender, sliding window, seq no rcvd: " + str(msgObj.AckSeq)) self.slideDataQueue(msgObj.AckSeq - (self.top('Win')) + 1) self.slideWindow(msgObj.AckSeq) else: if (msgObj.AckSeq == next_expected - 1): logger.info("Harsh: " + str(self._addr) + " Need to resend data with seq: " + str(next_expected)) # Resend packet at window[0] ##print "Resending AckSeq+1th packet" #print "Helloo Helloo" #print "This is the data am sending: ",self.top('Data').__hash__()," this is the sequence ",self.top('Win') self.wrap_send_buffer(self.top('Data'), self.top('Win'))
def checkSession(self): #print "I have been waiting for 35 seconds. this shit is not worth it.. I am leaving.." Timer.callLater( 0.1, lambda: self.getHigherProtocol().connectionLost( "Connection Lost Due to Inactivity"))
def __initiateFIN(self): hmac = self.__generateHMAC(self.__sym_key, "FIN") fin_msg = self.__buildDataMessage("FIN", hmac, "") self.__send(fin_msg) self.__state = FIN Timer.callLater(2,lambda:self.__checkConnectionState())
def __generalFailure(self, e): self.transport.write("Got error: %s\n" % e) Timer.callLater(.1, self.shutdown) return Failure
def __handleConnectionMessages(self, state, msgObj=None): if state == 0: self.__state = 0 self.__connected = 0 self.__handshake = 1 self.__currSeq = random.getrandbits(32) ##print "Preparing to send a SYN Message" ##print "The sequence number I am sending is :", self.__currSeq responseMessageBuilder = MessageData.GetMessageBuilder(PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("SYN") responseMessageBuilder["MessageSeq"].setData(self.__currSeq) responseMessageBuilder["AckSeq"].setData(0) responseMessageBuilder["Data"].setData("") # TODO Calculate the hash of the whole packet created above # and fill it in the HASH field of the packet msg_hash = self.hash_it(responseMessageBuilder) responseMessageBuilder["Hash"].setData(msg_hash) self.__waiting = 1 self.transport.writeMessage(responseMessageBuilder) Timer.callLater(0.1, lambda: self.checkState(0)) elif state == 1: # Server state where server received a SYN packet and will now send an SYNACK if (self.__state == 3 or self.__state == 2): ##print "Already Connected" return ##print "I have got a SYN and will now Send a SYNACK" self.__state = 1 self.__currSeq = random.getrandbits(32) #self.__curr_ackSeq = msgObj.MessageSeq ##print "The sequence number I got in the SYN is : ",msgObj.MessageSeq,"and the sequence number I am sending in the SYNACK is: ", self.__currSeq if (msgObj != None): self.__curr_ackSeq = msgObj.MessageSeq logger.debug( "Harsh: %s Hey! We got our SYN, setting curr_ackSeq to %d" % (self._addr, self.__curr_ackSeq)) #Prepare and send a SYNACK Message responseMessageBuilder = MessageData.GetMessageBuilder( PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("SYNACK") responseMessageBuilder["MessageSeq"].setData(self.__currSeq) responseMessageBuilder["AckSeq"].setData(self.__curr_ackSeq) responseMessageBuilder["Data"].setData("") msg_hash = self.hash_it(responseMessageBuilder) responseMessageBuilder["Hash"].setData(msg_hash) self.transport.writeMessage(responseMessageBuilder) Timer.callLater(0.1, lambda: self.checkState(1)) elif state == 2: if (self.__state >= 2): ##print "Multiple SYNACK, Discard" return self.__state = 2 ##print "I have got a SYNACK and will now send an ACK followed by data" ##print "The sequence number I got is : ",msgObj.MessageSeq, "and the sequence number i am sending is : ", self.__currSeq # Extract sequence number and set state variable self.__curr_ackSeq = msgObj.MessageSeq logger.debug( "Harsh: %s Hey! We got our SYNACK, setting curr_ackSeq to %d" % (self._addr, self.__curr_ackSeq)) #Prepare and send an ACK Message responseMessageBuilder = MessageData.GetMessageBuilder(PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("ACK") responseMessageBuilder["MessageSeq"].setData(0) responseMessageBuilder["AckSeq"].setData(msgObj.MessageSeq) responseMessageBuilder["Data"].setData("") #TODO Calculate the hash of the whole packet created above # and fill it in the HASH field of the packet msg_hash = self.hash_it(responseMessageBuilder) responseMessageBuilder["Hash"].setData(msg_hash) self.transport.writeMessage(responseMessageBuilder) ##print "sent an ACK , we are connected ,now sending Data:" ##print "Setting connected in client" self.__handshake = 1 self.__connected = 1 #self.__last_contig = self.__curr_ackSeq #set the timer #No timer because now data has to be sent, after sending ACK you don't # wait and start pushing data directly ##print "Sent Data" #print "Setting hb timer on receiver" self.__hb_timer = Timer.OneshotTimer(lambda: self.checkData()) self.__hb_timer.run(10) Timer.callLater(0.1, lambda: self.processQueue()) self.__session_timer = Timer.OneshotTimer( lambda: self.checkSession()) self.__session_timer.run(35) #Timer.callLater(0.1,lambda:self.checkState(2,msgObj)) #Check if the state has looped back to the same state. Store the current time # and check if it has changed after timeout elif state == 3: # Server side state, once server has received ACK from Client in response to SYNACK self.__state = 3 # Extract sequence number, check and set state variable ##print "I have got an ACK" #self.__currSeq = self.__currSeq +1 ##print "Setting connected in server" self.__connected = 1 self.__handshake = 1 self.__last_contig = msgObj.MessageSeq ##print "The sequence number I got is: ", msgObj.MessageSeq #print "Setting hb timer on sender" self.__hb_timer = Timer.OneshotTimer(lambda: self.checkData()) self.__hb_timer.run(10) self.__session_timer = Timer.OneshotTimer( lambda: self.checkSession()) self.__session_timer.run(35) elif state == 5: self.__state = 5 # Extract sequence number and set state variable ##print "I am going to send a FIN Message" self.__currSeq = self.__currSeq + 1 #Prepare and send an FIN Message responseMessageBuilder = MessageData.GetMessageBuilder(PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("FIN") responseMessageBuilder["MessageSeq"].setData(self.__currSeq) responseMessageBuilder["AckSeq"].setData(0) responseMessageBuilder["Data"].setData("") #TODO Calculate the hash of the whole packet created above # and fill it in the HASH field of the packet msg_hash = self.hash_it(responseMessageBuilder) responseMessageBuilder["Hash"].setData(msg_hash) self.transport.writeMessage(responseMessageBuilder) #set the timer self.__timely = Timer.callLater(0.1, lambda: self.checkState(5)) elif state == 6: ##print "I got a FIN Message and I will send a FINACK" self.__finhandshake = 1 self.__state = 6 self.__curr_ackSeq = msgObj.MessageSeq #Prepare and send an FINACK Message responseMessageBuilder = MessageData.GetMessageBuilder(PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("FINACK") responseMessageBuilder["MessageSeq"].setData(0) responseMessageBuilder["AckSeq"].setData(self.__curr_ackSeq) responseMessageBuilder["Data"].setData("") #TODO Calculate the hash of the whole packet created above # and fill it in the HASH field of the packet msg_hash = self.hash_it(responseMessageBuilder) responseMessageBuilder["Hash"].setData(msg_hash) ##print "Sending FINACK now: " self.transport.writeMessage(responseMessageBuilder) Timer.callLater( 0.1, lambda: self.getHigherProtocol().connectionLost( "Received FIN")) self.transport.loseConnection() self.__connected = 0 elif state == 7: ###print "I am suppose to send an ACK for data received:" responseMessageBuilder = MessageData.GetMessageBuilder(PTCLMessage) responseMessageBuilder["Hash"].setData('0') responseMessageBuilder["MessageType"].setData("ACK") responseMessageBuilder["MessageSeq"].setData(0) logger.info("Harsh: %s Sending ACK with ACK Sequence %d" % (self._addr, self.__curr_ackSeq)) responseMessageBuilder["AckSeq"].setData(self.__curr_ackSeq) # There is no data being piggy bagged on the ACK , if required put the data here from the # buffer where it is stored. responseMessageBuilder["Data"].setData("") responseMessageBuilder["Hash"].setData( self.hash_it(responseMessageBuilder)) self.transport.writeMessage(responseMessageBuilder) elif state == 8: self.__state = 8 self.__currSeq = 0 self.__curr_ackSeq = 0 ##print "I received a FINACK - Trying to terminate connection" ##print "dataList and rcvWindow are both empty, safe to terminate, connectionLost() called" Timer.callLater( 0.2, lambda: self.getHigherProtocol().connectionLost( "Received FINACK")) self.transport.loseConnection() if self.__timely: self.__timely.cancel() self.__connected = 0 else: pass
def initTimeout(self): self.idleTimeout = Timer.callLater(self.idleTimeoutPeriod, self.timeoutExpired)
def loseConnection(self): self.__fin_timer = Timer.OneshotTimer(lambda: self.checkWindow()) self.__fin_timer.run(0.1) #start FIN sequence """