def run ( self ): print("my peer id:",UserLib.mypeerid) #keep beginning time self.begtime=time.time() random.seed(time.time())#self.begtime) #try to open file to write received chunks. try: self.f=open(self.filename,'wb') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError at Leecher thread:",detail) self.terminate() return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception in Leecher thread:",detail) self.terminate() return #while thread should not terminate. t=self.begtime while UserDefs.Run: #If there are no peers in peer set, new connections should be established. #THIS WILL BE DONE IF CONNECTIONS ARE LESS THAN A THREASHOLD. if time.time()-t > UserDefs.PeerListReqInterval or not UserLib.DownConn_map: t=time.time() if not UserLib.DownConn_map: print("Empty connections") try: self.establish_connections() except UserLib.EstablishConnError as detail: print("establish connections error at Leecher thread:",detail) time.sleep(UserDefs.PeerListReqInterval) continue except UserLib.TerminateThread: break except Exception as detail: print("2.Unexpected Exception in Leecher thread:",detail) time.sleep(UserDefs.PeerListReqInterval) continue #NOW WE HAVE AS MUCH AS MAXDOWNCONN established connections and tokens to send requests. #but connections are choked.So watch the set to receive unchoke messages. self.sockset=[ temp[0] for temp in UserLib.DownConn_map ] try: inputready, outputready, exceptionready = select.select(self.sockset,[],[],UserDefs.SelectTimeout) except (ValueError, select.error) as detail: print("Select Exception in Leecher thread:",detail) continue #1.) In case a descripitor from your set has data that is state oriented msg. for s in inputready: #find position of socket having data into downloading connections map try: ind=[ temp[0]==s for temp in UserLib.DownConn_map].index(True) except ValueError as detail: print("Value Error at Leecher Thread:",detail,s) continue #try to receive message via socket indexed by ind. try: UserLib.SocketLock.acquire() self.msg_r=SocketLevel.recv_msg(ind, -1, UserLib.DownConn_map,True) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("3.ConnectionResetedByPeer in Leecher thread:") continue except Exception as detail: print("3.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() try: msgtype=self.msg_r['type'] except Exception as detail: print("4.Unexpected Exception in Leecher thread:",detail) continue if msgtype == 'unchoke': if self.unchokes == 0: print("First unchoke after:%.2f"%(time.time()-self.begtime),"seconds") self.unchokes+=1 UserLib.DownConn_map[ind][5]='unchoked' elif msgtype == 'choke': UserLib.DownConn_map[ind][5]='choked' #delete pending requests to chocking remote peer. UserLib.requests=[ r for r in UserLib.requests if not r[1] == UserLib.DownConn_map[ind][4]] elif msgtype == 'have': #update bitmap of peer having a new piece try: bitmap.bmp_setvalid(UserLib.DownConn_map[ind][3],self.msg_r['chunkno'],-1) #check if you are interested in this peer state=bitmap.interested(UserLib.bmp,UserLib.DownConn_map[ind][3],UserLib.BMPLENGTH,UserLib.lock) #if there is a change in your state about this peer except Exception: continue if UserLib.DownConn_map[ind][6]== 'uninterested' and state=='interested': #inform your map UserLib.DownConn_map[ind][6]=state #inform remote peer try: self.interested() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("5.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() #if received message is "block respose" #try to write block to resective position in file.: elif msgtype == 'block': chunkno=self.msg_r['chunkpos'] try: self.block(ind,self.msg_r) #Exception indication requested block is not available #to peer last request was send. except UserLib.BlockCorrupted: print("6.BlockCorrupted in Leecher thread:") continue except UserLib.UnexpectedBlock: #print("6.UnexpectedBlock in Leecher thread:") continue #Uppon Exception Terminate thread except Exception as detail: print("6.Unexpected Exception in Leecher thread:",detail) continue self.have(chunkno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("7.1.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() i=len(UserLib.UpConn_map)-1 UserLib.SocketLock.acquire() while i >=0: try: if UserLib.DownConn_map[ind][4]==UserLib.UpConn_map[i][2]: i-=1 continue except Exception as detail: i-=1 print("7.1.2.Unexpected Exception in Lecher thread:",detail,ind,UserLib.UpConn_map,UserLib.DownConn_map) continue #inform all downloaders directly conected to you that you #receive a new piece. try: #UserLib.SocketLock.acquire() SocketLevel.send_msg(i,-1,UserLib.UpConn_map,self.msg) except Exception as detail: i=len(UserLib.UpConn_map)-1 print("7.2.Unexpected Exception in Lecher thread:",detail,i,len(UserLib.UpConn_map)) else: i-=1 #finally: # UserLib.SocketLock.release() UserLib.SocketLock.release() for i in range(0,len(UserLib.DownConn_map)): try: state=bitmap.interested(UserLib.bmp,UserLib.DownConn_map[i][3],UserLib.BMPLENGTH,UserLib.lock) except Exception: continue if UserLib.DownConn_map[i][6]=='interested' and state=='uninterested': UserLib.DownConn_map[i][6]=state try: #print("here",UserLib.DownConn_map,UserLib.bmp) self.uninterested() UserLib.SocketLock.acquire() SocketLevel.send_msg(i,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("9.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() #select block and uploader. try: ind, self.blockno =self.select_block() except UserLib.FileCompletelyDownloaded: break except UserLib.AllConnectionsChoked: #print("11.AllConnectionsChoked or unintetresting in Leecher thread") continue except UserLib.MaxRequestsSent: #print("11.MaxRequestsSent in Leecher thread") continue except Exception as detail: print("11.Unexpected Exception in Leecher thread:",detail) break #if it is a pending block request, dont do anything. #prepare request for the selected block. self.request(self.blockno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("12.Unexpected Exception in Leecher thread:",detail) continue else: UserLib.requests.append([self.blockno,UserLib.DownConn_map[ind][4],0]) finally: UserLib.SocketLock.release() #while Run #make "clen up" job and terminate thread. self.terminate() return
def run(self): print("my peer id:", UserLib.mypeerid) #keep beginning time self.begtime = time.time() random.seed(time.time()) #self.begtime) #try to open file to write received chunks. try: self.f = open(self.filename, 'wb') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError at Leecher thread:", detail) self.terminate() return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception in Leecher thread:", detail) self.terminate() return #while thread should not terminate. t = self.begtime while UserDefs.Run: #If there are no peers in peer set, new connections should be established. #THIS WILL BE DONE IF CONNECTIONS ARE LESS THAN A THREASHOLD. if time.time( ) - t > UserDefs.PeerListReqInterval or not UserLib.DownConn_map: t = time.time() if not UserLib.DownConn_map: print("Empty connections") try: self.establish_connections() except UserLib.EstablishConnError as detail: print("establish connections error at Leecher thread:", detail) time.sleep(UserDefs.PeerListReqInterval) continue except UserLib.TerminateThread: break except Exception as detail: print("2.Unexpected Exception in Leecher thread:", detail) time.sleep(UserDefs.PeerListReqInterval) continue #NOW WE HAVE AS MUCH AS MAXDOWNCONN established connections and tokens to send requests. #but connections are choked.So watch the set to receive unchoke messages. self.sockset = [temp[0] for temp in UserLib.DownConn_map] try: inputready, outputready, exceptionready = select.select( self.sockset, [], [], UserDefs.SelectTimeout) except (ValueError, select.error) as detail: print("Select Exception in Leecher thread:", detail) continue #1.) In case a descripitor from your set has data that is state oriented msg. for s in inputready: #find position of socket having data into downloading connections map try: ind = [temp[0] == s for temp in UserLib.DownConn_map].index(True) except ValueError as detail: print("Value Error at Leecher Thread:", detail, s) continue #try to receive message via socket indexed by ind. try: UserLib.SocketLock.acquire() self.msg_r = SocketLevel.recv_msg(ind, -1, UserLib.DownConn_map, True) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("3.ConnectionResetedByPeer in Leecher thread:") continue except Exception as detail: print("3.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() try: msgtype = self.msg_r['type'] except Exception as detail: print("4.Unexpected Exception in Leecher thread:", detail) continue if msgtype == 'unchoke': if self.unchokes == 0: print( "First unchoke after:%.2f" % (time.time() - self.begtime), "seconds") self.unchokes += 1 UserLib.DownConn_map[ind][5] = 'unchoked' elif msgtype == 'choke': UserLib.DownConn_map[ind][5] = 'choked' #delete pending requests to chocking remote peer. UserLib.requests = [ r for r in UserLib.requests if not r[1] == UserLib.DownConn_map[ind][4] ] elif msgtype == 'have': #update bitmap of peer having a new piece try: bitmap.bmp_setvalid(UserLib.DownConn_map[ind][3], self.msg_r['chunkno'], -1) #check if you are interested in this peer state = bitmap.interested(UserLib.bmp, UserLib.DownConn_map[ind][3], UserLib.BMPLENGTH, UserLib.lock) #if there is a change in your state about this peer except Exception: continue if UserLib.DownConn_map[ind][ 6] == 'uninterested' and state == 'interested': #inform your map UserLib.DownConn_map[ind][6] = state #inform remote peer try: self.interested() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("5.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() #if received message is "block respose" #try to write block to resective position in file.: elif msgtype == 'block': chunkno = self.msg_r['chunkpos'] try: self.block(ind, self.msg_r) #Exception indication requested block is not available #to peer last request was send. except UserLib.BlockCorrupted: print("6.BlockCorrupted in Leecher thread:") continue except UserLib.UnexpectedBlock: #print("6.UnexpectedBlock in Leecher thread:") continue #Uppon Exception Terminate thread except Exception as detail: print("6.Unexpected Exception in Leecher thread:", detail) continue self.have(chunkno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("7.1.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() i = len(UserLib.UpConn_map) - 1 UserLib.SocketLock.acquire() while i >= 0: try: if UserLib.DownConn_map[ind][ 4] == UserLib.UpConn_map[i][2]: i -= 1 continue except Exception as detail: i -= 1 print( "7.1.2.Unexpected Exception in Lecher thread:", detail, ind, UserLib.UpConn_map, UserLib.DownConn_map) continue #inform all downloaders directly conected to you that you #receive a new piece. try: #UserLib.SocketLock.acquire() SocketLevel.send_msg(i, -1, UserLib.UpConn_map, self.msg) except Exception as detail: i = len(UserLib.UpConn_map) - 1 print("7.2.Unexpected Exception in Lecher thread:", detail, i, len(UserLib.UpConn_map)) else: i -= 1 #finally: # UserLib.SocketLock.release() UserLib.SocketLock.release() for i in range(0, len(UserLib.DownConn_map)): try: state = bitmap.interested( UserLib.bmp, UserLib.DownConn_map[i][3], UserLib.BMPLENGTH, UserLib.lock) except Exception: continue if UserLib.DownConn_map[i][ 6] == 'interested' and state == 'uninterested': UserLib.DownConn_map[i][6] = state try: #print("here",UserLib.DownConn_map,UserLib.bmp) self.uninterested() UserLib.SocketLock.acquire() SocketLevel.send_msg(i, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print( "9.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() #select block and uploader. try: ind, self.blockno = self.select_block() except UserLib.FileCompletelyDownloaded: break except UserLib.AllConnectionsChoked: #print("11.AllConnectionsChoked or unintetresting in Leecher thread") continue except UserLib.MaxRequestsSent: #print("11.MaxRequestsSent in Leecher thread") continue except Exception as detail: print("11.Unexpected Exception in Leecher thread:", detail) break #if it is a pending block request, dont do anything. #prepare request for the selected block. self.request(self.blockno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("12.Unexpected Exception in Leecher thread:", detail) continue else: UserLib.requests.append( [self.blockno, UserLib.DownConn_map[ind][4], 0]) finally: UserLib.SocketLock.release() #while Run #make "clen up" job and terminate thread. self.terminate() return
def establish_connection(listeningports,listeningips,peerids,connections,i): #try to create a socket and send a TCP connection request to each peer of the set. try: newsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) newsock.connect ((listeningips[i], listeningports[i])) #Uppon Exception close recently created socket and raise Exception. except socket.error: print("<establish_connection>:: Socket Error Unable to establish connection with peer at port:",listeningports[i]) newsock.close() raise #Uppon Exception close recently created socket and raise Exception. except Exception as detail: print("<establish_connection>:: Unexpected exception Unable to establish connection with peer at port:",listeningports[i],":",detail) newsock.close() raise #Uppon success, append to connections map a tuple containing (socket, port, #counter of blocks received, bitmap, peerid, and state info) of recently #established connection. connections.append([newsock,listeningports[i],0,[],0,'choked','',listeningips[i],0]) #create and send handshake message msg={'type':'handshake' ,'metadata_hash':UserLib.metadata_hash ,'peer_id':UserLib.mypeerid } try: SocketLevel.send_msg(len(connections)-1,-1,connections,msg, True) except Exception as detail: print("<establish_connection>:: 1.Unable to establish connection with peer at port:",listeningports[i],":",detail) raise #receive handshake response try: msg_r=SocketLevel.recv_msg(len(connections)-1, -1, connections, True) except Exception as detail: print("<establish_connection>:: 2.Unable to establish connection with peer at port:",listeningports[i],":",detail) raise else: #if not a handshake response received, ro peed id received is not valid. if not msg_r['type'] == 'handshake_response' or not msg_r['peerid'] in peerids: print("------------------------>",msg_r) newsock.close() #remove socket from connections map. del connections[-1] raise UserLib.UnexpectedMessage else: #keep peer id from last message. peerid=msg_r['peerid'] #receive bitmap of recently appened peer. try: msg_r=SocketLevel.recv_msg(len(connections)-1, -1, connections,True) except Exception as detail: print("<establish_connection>:: 4.Unable to establish connection with peer at port:",listeningports[i],":",detail) raise if not msg_r['type'] == 'bitfield': newsock.close() #remove socket from connections map. del connections[-1] raise UserLib.UnexpectedMessage connections[-1][3]=msg_r['bmp'] connections[-1][4]=peerid #check if u are interested in blocks of this remote peer or not. try: connections[-1][6]=bitmap.interested(UserLib.bmp,msg_r['bmp'],msg_r['bmplen'],UserLib.lock) except Exception as detail: print("<establish_connection>:: 5.Unable to establish connection with peer at port:",listeningports[i],":",detail) #remove socket from connections map. del connections[-1] raise if connections[-1][6]=='uninterested': msg={'type':'uninterested'} else: msg={'type':'interested'} #inform this remote peer if interested or not. try: SocketLevel.send_msg(len(connections)-1,-1,connections,msg,True) except Exception as detail: print("<establish_connection>:: 6.Unable to establish connection with peer at port:",listeningports[i],":",detail) raise