def terminate(self): self.f.close() for s in self.sockset: #if not s==sys.stdin: s.close() print(self.getName(), " is going to terinate\n") print("Pieces sent:", UserLib.BlocksSent) print("Messages Sent:", UserLib.MessagesSent) print("Interested Received:", UserLib.InterestedReceived) print("Uninterested Received:", UserLib.UninterestedReceived) print("Interested Sent:", UserLib.InterestedSent) print("Uninterested Sent:", UserLib.UninterestedSent) print("Optimistic Unchokes Received:", UserLib.OptUnchokesReceived) print("Regular Unchokes Received:", UserLib.RegUnchokesReceived) if not UserLib.OptUnchokesReceived == 0: print("Interested connected peers per Opt Unchoke:%.2f" % (UserLib.InterestedPeersAtOpt / UserLib.OptUnchokesReceived)) print("OptUnchokeTimes:", UserLib.OptUnchokeTimes) print("RegUnchokeTimes:", UserLib.RegUnchokeTimes) print("Uploading_t:", UserLib.Uploading_t) print("Downloading_t:", UserLib.Downloading_t) print("InterestedMsgReceived_t:", UserLib.InterestedMsgReceived_t) msg = {'type': 'leave'} SocketLevel.send_msg(-1, self.tracker, [], msg) return
def terminate(self): self.f.close() for s in self.sockset: #if not s==sys.stdin: s.close() print(self.getName()," is going to terinate\n") print("Pieces sent:",UserLib.BlocksSent) print("Messages Sent:",UserLib.MessagesSent) print("Interested Received:",UserLib.InterestedReceived) print("Uninterested Received:",UserLib.UninterestedReceived) print("Interested Sent:",UserLib.InterestedSent) print("Uninterested Sent:",UserLib.UninterestedSent) print("Optimistic Unchokes Received:",UserLib.OptUnchokesReceived) print("Regular Unchokes Received:",UserLib.RegUnchokesReceived) if not UserLib.OptUnchokesReceived == 0: print("Interested connected peers per Opt Unchoke:%.2f"%(UserLib.InterestedPeersAtOpt/UserLib.OptUnchokesReceived)) print("OptUnchokeTimes:",UserLib.OptUnchokeTimes) print("RegUnchokeTimes:",UserLib.RegUnchokeTimes) print("Uploading_t:",UserLib.Uploading_t) print("Downloading_t:",UserLib.Downloading_t) print("InterestedMsgReceived_t:",UserLib.InterestedMsgReceived_t) msg={'type':'leave'} SocketLevel.send_msg(-1, self.tracker, [],msg) return
def get_peerset(self): #remove port's and ip's from your set. self.listeningports=[] self.listeningips=[] #request a new peer set. while UserDefs.Run: #prepare message self.peer_request() #try to send it to coordinator try: SocketLevel.send_msg(-1, self.tracker, [], self.msg) except Exception as detail: print("<get_peerset>:: 1.Exception while contacting coordinator.:",detail) raise #receive request from coordinator try: msg=SocketLevel.recv_msg(-1, self.tracker, []) #for each peer of the received set keep its ip,port and id. self.listeningports=msg['listeningports'] self.listeningips=msg['listeningips'] self.peerids=msg['peerids'] i=len(self.listeningports)-1 while i>=0: if self.listeningports[i] in [ temp[0] for temp in UserLib.TimedOutPeers ] \ and self.listeningips[i] in [ temp[1] for temp in UserLib.TimedOutPeers ]: del self.listeningports[i] del self.listeningips[i] del self.peerids[i] i-=1 #if identifier of current peer is present in received set try: mypos=self.peerids.index(UserLib.mypeerid) except ValueError as detail: print("<get_peerset>::wtf???",detail) pass #remove it, and its ip and its port, since it is useless to try #to establish connection with tself. else: del self.listeningports[mypos] del self.listeningips[mypos] del self.peerids[mypos] #Uppon Exception raise it except Exception as detail: print("<get_peerset>:: 2.Exception in while contacting coordinator.",detail) raise if not self.listeningports: #if there is no peer in swarm wait 15 seconds #before you ask again a list of listening peers. time.sleep(UserDefs.PeerListReqInterval) else: break #print("--------------") #print('active peer set:','\n',self.listeningports,'\n',self.listeningips,'\n',self.peerids) #print("-------------") if not UserDefs.Run: raise UserLib.TerminateThread return
def main(): global msg, msg_r if not len(sys.argv) in [7, 8]: print( "Usage:", sys.argv[0], "(<trackerip> <trackerport>) <listeningport> <seed/peer> <filename> <optimistic/optimal> [<create metadata file>]" ) return #assign command line arguments to local variables trackerip = socket.gethostbyname(sys.argv[1]) trackerport = int(sys.argv[2]) listeningport = int(sys.argv[3]) hostname = socket.gethostname() listeningip = socket.gethostbyname(hostname) mode = sys.argv[4] filename = sys.argv[5] choice = sys.argv[6] print(trackerip, trackerport, listeningip, listeningport, mode, filename, choice) #The first uploader is also the creator of metadata file. #All other peers receiving metadata file from a site #acting as a global directory. if len(sys.argv) == 8 and sys.argv[7] == "create": metadata_dict = metadataLib.create_metadatafile(filename) else: metadata_dict = metadataLib.read_metadatafile(filename) print("size of metadata") if mode == "peer": #create file so that following server and leecher thread open it. try: filename = filename + str(listeningport) f = open(filename, 'wb+') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError:", detail) return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception:", detail) return else: f.close() #initialize bitmap, sha1's of each chunk and file identifier(metadata hash). UserLib.BMPLENGTH = math.ceil(metadata_dict['filesize'] / UserDefs.PieceSize) bitmap.bmp_init(UserLib.bmp, UserLib.BMPLENGTH) UserLib.sha1s_map = metadata_dict['sha1s_map'] UserLib.metadata_hash = metadata_dict['metadata_hash'] #print("metadata_hash",UserLib.metadata_hash) #In seeder mode all blocks are available. if mode == "seed": bitmap.bmp_setallvalid(UserLib.bmp, UserLib.BMPLENGTH) #creation of a socket to establish TCP connection with coordinator. try: tracker = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tracker.connect((trackerip, trackerport)) except socket.error as detail: print("Tracker communication Socket error", detail) return except Exception as detail: print("Unexpected Exception:", detail) return #prepare a "join_swarm" message" to send to coordinator. join_swarm(metadata_dict['filename'], metadata_dict['filesize'], metadata_dict['FileMd5'], listeningip, listeningport) try: SocketLevel.send_msg(-1, tracker, [], msg) except Exception as detail: print("Unexpected Exception:", detail) tracker.close() return #receive a "join_response" message from coordinator. try: msg_r = SocketLevel.recv_msg(-1, tracker, []) except Exception as detail: print("Unexpected Exception:", detail) tracker.close() return #upon successful communication retrieve your peer identifier. else: UserLib.mypeerid = msg_r['peerid'] #constructor of "ServerThread" for that peer #size, md5 and name of file to seed #port and ip listening for requests of TCP connections #socket of established connection with coordinator. Sthread = ServerThread.ServerThread(metadata_dict['filesize'], metadata_dict['FileMd5'], filename, listeningport, listeningip, mode, choice, tracker) Sthread.start() #constructor of "LeecherThread" for that peer-if not in seeder mode. if mode == "peer": Lthread = LeecherThread.LeecherThread(metadata_dict['filesize'], metadata_dict['FileMd5'], filename, listeningport, listeningip, tracker) Lthread.start() #Main Thread waiting threads to terminate. Sthread.join() if sys.argv[3] == "peer": Lthread.join() tracker.close() print('Programm is going to terminate') return
def get_peerset(self): #remove port's and ip's from your set. self.listeningports = [] self.listeningips = [] #request a new peer set. while UserDefs.Run: #prepare message self.peer_request() #try to send it to coordinator try: SocketLevel.send_msg(-1, self.tracker, [], self.msg) except Exception as detail: print( "<get_peerset>:: 1.Exception while contacting coordinator.:", detail) raise #receive request from coordinator try: msg = SocketLevel.recv_msg(-1, self.tracker, []) #for each peer of the received set keep its ip,port and id. self.listeningports = msg['listeningports'] self.listeningips = msg['listeningips'] self.peerids = msg['peerids'] i = len(self.listeningports) - 1 while i >= 0: if self.listeningports[i] in [ temp[0] for temp in UserLib.TimedOutPeers ] \ and self.listeningips[i] in [ temp[1] for temp in UserLib.TimedOutPeers ]: del self.listeningports[i] del self.listeningips[i] del self.peerids[i] i -= 1 #if identifier of current peer is present in received set try: mypos = self.peerids.index(UserLib.mypeerid) except ValueError as detail: print("<get_peerset>::wtf???", detail) pass #remove it, and its ip and its port, since it is useless to try #to establish connection with tself. else: del self.listeningports[mypos] del self.listeningips[mypos] del self.peerids[mypos] #Uppon Exception raise it except Exception as detail: print( "<get_peerset>:: 2.Exception in while contacting coordinator.", detail) raise if not self.listeningports: #if there is no peer in swarm wait 15 seconds #before you ask again a list of listening peers. time.sleep(UserDefs.PeerListReqInterval) else: break #print("--------------") #print('active peer set:','\n',self.listeningports,'\n',self.listeningips,'\n',self.peerids) #print("-------------") if not UserDefs.Run: raise UserLib.TerminateThread 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 run(self): random.seed(time.time()) #create a socket, bind it to your listening ip and port #in order to listen for incoming TCP connection requests. try: server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((self.listeningip, self.listeningport)) server.listen(1) #Uppon Exception close listening socket and terminate thread. except (socket.error, socket.gaierror, OverflowError) as detail: print("Listening Socket error:", detail) server.close() UserDefs.Run = False return #Open file to seed. try: self.f = open(self.filename, 'rb') except IOError as detail: print("IOError Opening File", detail) self.terminate() except Exception as detail: print("Unexpected Exception opening file at server thread:", detail) self.terminate() #Loop forever while UserDefs.Run: self.sockset = [temp[0] for temp in UserLib.UpConn_map] if len(UserLib.UpConn_map) == UserDefs.ActiveSetSize: #print("max size") self.sockset = self.sockset + [sys.stdin] else: self.sockset = self.sockset + [server, sys.stdin] # wait till a socket has data. try: inputready, outputready, exceptionready = select.select( self.sockset, [], []) except ValueError as detail: print("select at server thread:", detail, self.sockset) #search on which socket there are available data. for s in inputready: #if it is in server socket, it is a TCP connection request. if s == server: if len(UserLib.UpConn_map) == UserDefs.ActiveSetSize: continue try: conn, addr = server.accept() conn.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except socket.timeout: print("timeout") pass except Exception as detail: print("Accepting connection error:", detail) #Uppon success, append socket into watched set. #append socket, peer ip and port, peer id and connection's #state info to Uploading connections map. else: #if len(UserLib.UpConn_map)>=UserDefs.ActiveSetSize: # print("here") # conn.close() # continue self.sockset.append(conn) UserLib.UpConn_map.append([ conn, conn.getpeername(), 0, 'choked', 'uninterested', False, 0, 0, 0 ]) elif s == sys.stdin: ##command = s.readline() ##if command == 'quit\n': UserDefs.Run = False break #otherwise there are data in socket of an established connection. else: #find position of current socket into uploading connections map try: ind = [temp[0] == s for temp in UserLib.UpConn_map].index(True) except ValueError as detail: print("Unable to index connection at server 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.UpConn_map) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("2. ConnectionResetedByPeer at Server Thread:") UserLib.SocketLock.release() self.unchoke() continue except Exception as detail: print("2. Unexpected exception at Server Thread:", detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() try: msgtype = self.msg_r['type'] except Exception as detail: print("Key error at Server Thread:", detail) self.unchoke() continue #if message is a "block request" if msgtype == 'request': #create and send response via socket s. try: self.block(self.msg_r) UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.UpConn_map, self.msg) UserLib.UpConn_map[ind][7] += 1 #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("3. Unexpected exception at Server Thread:", detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() #if message is a "handshake request" elif msgtype == 'handshake': #check file id of requested file. #Connection should be closed if not self.msg_r[ 'metadata_hash'] == UserLib.metadata_hash: print("Unable to seed requested file") s.close() del UserLib.UpConn_map[ind] continue #response including peer id of current peer. try: self.handshake_response() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.UpConn_map, self.msg) #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("4. Unexpected exception at Server Thread:", detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() #send bitmap to remote peer. try: self.bitfield() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.UpConn_map, self.msg) #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("5. Unexpected exception at Server Thread:", detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() UserLib.UpConn_map[ind][5] = True try: print('\nNew Leecher:', s.getpeername(), "#accepted connections:", len(UserLib.UpConn_map), " ", time.time()) except Exception as detail: print("5.1 Unexpected exception at Server Thread:", detail) pass #and add peer identifier after a successful handshake. UserLib.UpConn_map[ind][2] = self.msg_r['peer_id'] elif msgtype == 'interested': UserLib.UpConn_map[ind][4] = 'interested' if UserLib.UpConn_map[ind][5] == 'unchoked': self.unchoke() if self.unchokeinvoked == 0: self.unchoke() self.unchokeinvoked = 1 elif msgtype == 'uninterested': UserLib.UpConn_map[ind][4] = 'uninterested' if UserLib.UpConn_map[ind][3] == 'unchoked': self.unchoke() #acknowledgment received. elif msgtype == 'have': UserLib.UpConn_map[ind][6] = self.msg_r['interested'] #iii=[] #for i in range(0,len(UserLib.UpConn_map)): # if UserLib.UpConn_map[i][4]=='interested': # iii.append(UserLib.UpConn_map[i][6]) #print("iii:",iii) continue #unexpected message. else: print('Unexpected message type:', msgtype) continue #make "clean up" job. self.terminate() return
def unchoke(self): #reset timer self.timer.cancel() ##if there are active connections to your uploading set cancel and reset unchoke. if not UserLib.UpConn_map: self.unchokeflag = 0 self.unchokeinvoked = 0 return UserLib.SocketLock.acquire() if self.mode == 'seed': suggestedOpt = -1 mymin = 10000 #remote peers (downloaders) that were recently (less than 20 seconds) unchoked remotedownloaders1 = [] #rest of remote peer remotedownloaders2 = [] curtime = time.time() for i in range(0, len(UserLib.UpConn_map)): unchoketime = UserLib.UpConn_map[i][8] if curtime - unchoketime < UserDefs.RecentUnchokeInterval: remotedownloaders1.append([unchoketime, i]) else: remotedownloaders2.append([UserLib.UpConn_map[i][7], i]) if UserLib.UpConn_map[i][6] < mymin: mymin = UserLib.UpConn_map[i][6] suggestedOpt = [0, i] remotedownloaders1.sort(reverse=True) remotedownloaders2.sort(reverse=True) remotedownloaders = remotedownloaders1 + remotedownloaders2 if self.unchokeflag in [0, 1]: if time.time( ) - self.lastunchoketime >= 3 * UserDefs.UnchokeInterval: self.lastunchoketime = time.time() if self.choice == 'optimistic': self.plannedOpt = random.choice(remotedownloaders) elif self.choice == 'optimal': self.plannedOpt = suggestedOpt try: peerpos = self.plannedOpt[1] UserLib.UpConn_map[peerpos][3] = 'unchoked' SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, { 'type': 'unchoke', 'mode': 'opt' }) UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>::1.Unexpected exception: ", detail) for i in range(0, len(remotedownloaders)): peerpos = remotedownloaders[i][1] if not self.plannedOpt: continue elif self.plannedOpt[1] == remotedownloaders[i][1]: continue if i < UserDefs.RegularUnchokedNum: try: UserLib.UpConn_map[peerpos][3] = 'unchoked' except Exception as detail: print("<unchoke>:: 2.Unexpected exception:", detail) continue msg = {'type': 'unchoke', 'mode': 'reg'} else: try: UserLib.UpConn_map[peerpos][3] = 'choked' except Exception as detail: print("<unchoke>:: 2.Unexpected exception:", detail) continue msg = {'type': 'choke'} try: SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, msg) if msg['type'] == 'unchoke': UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ", detail) continue else: for i in range(0, len(remotedownloaders)): peerpos = remotedownloaders[i][1] if i < UserDefs.RegularUnchokedNum + 1: #print("296:",peerpos,len(UserLib.UpConn_map)) try: UserLib.UpConn_map[peerpos][3] = 'unchoked' except Exception as detail: print("<unchoke>:: 3.Unexpected exception:", detail) continue msg = {'type': 'unchoke', 'mode': 'reg'} else: try: UserLib.UpConn_map[peerpos][3] = 'choked' except Exception as detail: print("<unchoke>:: 4.Unexpected exception:", detail) continue msg = {'type': 'choke'} try: SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, msg) if msg['type'] == 'unchoke': UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ", detail) continue #####--------------- else: interestedpeers = [] remoteuploaders = [] suggestedOpt = -1 mymin = 10000 for i in range(0, len(UserLib.UpConn_map)): #for all remote peers (downloaders) that are interested to your content if UserLib.UpConn_map[i][4] == 'interested': #keep their peer identifier peerid = UserLib.UpConn_map[i][2] interestedpeers.append([0, peerid, i]) if UserLib.UpConn_map[i][6] < mymin: mymin = UserLib.UpConn_map[i][6] suggestedOpt = [0, peerid, i] #and if they are also uploaders to you if peerid in [s[4] for s in UserLib.DownConn_map]: #find their position in the map of your downloaders peerpos = [ peerid == s[4] for s in UserLib.DownConn_map ].index(True) #and for everyone that have send you at least one block at the last 30 seconds if UserLib.DownConn_map[peerpos][2] > 0 and time.time( ) - UserLib.DownConn_map[peerpos][ 8] < 3 * UserDefs.UnchokeInterval: #keep position in uploading map, their peer id and number of blocks having sent to you. remoteuploaders.append( [UserLib.DownConn_map[peerpos][2], peerid, i]) if len(interestedpeers) > 0: if self.unchokeflag == 0 and time.time( ) - self.lastunchoketime >= 3 * UserDefs.UnchokeInterval: self.lastunchoketime = time.time() if self.choice == 'optimistic': self.plannedOpt = random.choice(interestedpeers) elif self.choice == 'optimal': self.plannedOpt = suggestedOpt msg = {'type': 'unchoke', 'mode': 'opt'} #print("1-->",self.plannedOpt,interestedpeers) #print("Opt unchoke",peerpos); try: peerpos = self.plannedOpt[2] UserLib.UpConn_map[peerpos][3] = 'unchoked' SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, msg) UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>:: 5.Unexpected exception: ", detail) #remote uploaders consists of [#blocks received, peerid, position at map of uploaders] for every remote uploader. remoteuploaders.sort(reverse=True) regularunchoked = [] if not remoteuploaders: regularunchoked = [] elif len(remoteuploaders) <= UserDefs.RegularUnchokedNum: regularunchoked = remoteuploaders else: for i in range(0, UserDefs.RegularUnchokedNum): regularunchoked.append(remoteuploaders[i]) #print("remote uploaders:",remoteuploaders) #print("The three fastest peers(Regular Unchoked) are:",regularunchoked) #print("planned optimistic unchoked:",self.plannedOpt) #print("2-->",self.plannedOpt) for i in range(0, len(remoteuploaders)): if remoteuploaders[i] == self.plannedOpt: continue try: peerpos = remoteuploaders[i][2] if remoteuploaders[i] in regularunchoked: msg = {'type': 'unchoke', 'mode': 'reg'} UserLib.UpConn_map[peerpos][3] = 'unchoked' else: msg = {'type': 'choke'} UserLib.UpConn_map[peerpos][3] = 'choked' except IndexError: continue try: SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, msg) if msg['type'] == 'unchoke': UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ", detail) continue if not self.plannedOpt: pass elif self.plannedOpt[1] in [s[1] for s in regularunchoked]: while True: peerpos = random.randint(0, len(UserLib.UpConn_map) - 1) peerid = UserLib.UpConn_map[peerpos][2] self.plannedOpt = [0, peerid, peerpos] msg = {'type': 'unchoke', 'mode': 'reg'} UserLib.UpConn_map[peerpos][3] = 'unchoked' try: SocketLevel.send_msg(peerpos, -1, UserLib.UpConn_map, msg) UserLib.UpConn_map[peerpos][8] = time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ", detail) continue if UserLib.UpConn_map[peerpos][4] == 'interested': break UserLib.SocketLock.release() #if thread has not terminated if UserDefs.Run: self.timer = threading.Timer(UserDefs.UnchokeInterval, self.unchoke) self.timer.start() self.unchokeflag = (self.unchokeflag + 1) % 3
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 main(): global msg, msg_r if not len(sys.argv) in [7,8]: print("Usage:",sys.argv[0],"(<trackerip> <trackerport>) <listeningport> <seed/peer> <filename> <optimistic/optimal> [<create metadata file>]") return #assign command line arguments to local variables trackerip=socket.gethostbyname(sys.argv[1]) trackerport=int(sys.argv[2]) listeningport=int(sys.argv[3]) hostname=socket.gethostname() listeningip=socket.gethostbyname(hostname) mode=sys.argv[4] filename=sys.argv[5] choice=sys.argv[6] print(trackerip,trackerport,listeningip,listeningport,mode,filename,choice) #The first uploader is also the creator of metadata file. #All other peers receiving metadata file from a site #acting as a global directory. if len(sys.argv) == 8 and sys.argv[7] == "create": metadata_dict=metadataLib.create_metadatafile(filename) else: metadata_dict=metadataLib.read_metadatafile(filename) print("size of metadata") if mode == "peer": #create file so that following server and leecher thread open it. try: filename=filename+str(listeningport) f=open(filename,'wb+') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError:",detail) return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception:",detail) return else: f.close() #initialize bitmap, sha1's of each chunk and file identifier(metadata hash). UserLib.BMPLENGTH=math.ceil(metadata_dict['filesize']/UserDefs.PieceSize) bitmap.bmp_init(UserLib.bmp,UserLib.BMPLENGTH) UserLib.sha1s_map=metadata_dict['sha1s_map'] UserLib.metadata_hash=metadata_dict['metadata_hash'] #print("metadata_hash",UserLib.metadata_hash) #In seeder mode all blocks are available. if mode == "seed": bitmap.bmp_setallvalid(UserLib.bmp,UserLib.BMPLENGTH) #creation of a socket to establish TCP connection with coordinator. try: tracker = socket.socket ( socket.AF_INET, socket.SOCK_STREAM ) tracker.connect((trackerip,trackerport )) except socket.error as detail: print("Tracker communication Socket error",detail) return except Exception as detail: print("Unexpected Exception:",detail) return #prepare a "join_swarm" message" to send to coordinator. join_swarm(metadata_dict['filename'],metadata_dict['filesize'],metadata_dict['FileMd5'],listeningip,listeningport) try: SocketLevel.send_msg(-1,tracker,[],msg) except Exception as detail: print("Unexpected Exception:",detail) tracker.close() return #receive a "join_response" message from coordinator. try: msg_r=SocketLevel.recv_msg(-1,tracker,[]) except Exception as detail: print("Unexpected Exception:",detail) tracker.close() return #upon successful communication retrieve your peer identifier. else: UserLib.mypeerid=msg_r['peerid'] #constructor of "ServerThread" for that peer #size, md5 and name of file to seed #port and ip listening for requests of TCP connections #socket of established connection with coordinator. Sthread=ServerThread.ServerThread(metadata_dict['filesize'],metadata_dict['FileMd5'],filename,listeningport,listeningip,mode,choice,tracker) Sthread.start() #constructor of "LeecherThread" for that peer-if not in seeder mode. if mode == "peer": Lthread=LeecherThread.LeecherThread(metadata_dict['filesize'],metadata_dict['FileMd5'],filename,listeningport,listeningip,tracker) Lthread.start() #Main Thread waiting threads to terminate. Sthread.join() if sys.argv[3] == "peer": Lthread.join() tracker.close() print('Programm is going to 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
def run (self): random.seed(time.time()) #create a socket, bind it to your listening ip and port #in order to listen for incoming TCP connection requests. try: server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM ) server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind((self.listeningip, self.listeningport)) server.listen ( 1 ) #Uppon Exception close listening socket and terminate thread. except (socket.error,socket.gaierror,OverflowError) as detail: print("Listening Socket error:",detail) server.close() UserDefs.Run=False return #Open file to seed. try: self.f=open(self.filename,'rb') except IOError as detail: print("IOError Opening File",detail) self.terminate() except Exception as detail: print("Unexpected Exception opening file at server thread:",detail) self.terminate() #Loop forever while UserDefs.Run: self.sockset=[ temp[0] for temp in UserLib.UpConn_map ] if len(UserLib.UpConn_map)==UserDefs.ActiveSetSize: #print("max size") self.sockset=self.sockset+[sys.stdin] else: self.sockset=self.sockset+[server,sys.stdin] # wait till a socket has data. try: inputready, outputready, exceptionready = select.select(self.sockset,[],[]) except ValueError as detail: print("select at server thread:",detail,self.sockset) #search on which socket there are available data. for s in inputready: #if it is in server socket, it is a TCP connection request. if s == server: if len(UserLib.UpConn_map)==UserDefs.ActiveSetSize: continue try: conn, addr=server.accept() conn.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) except socket.timeout: print("timeout") pass except Exception as detail: print("Accepting connection error:",detail) #Uppon success, append socket into watched set. #append socket, peer ip and port, peer id and connection's #state info to Uploading connections map. else: #if len(UserLib.UpConn_map)>=UserDefs.ActiveSetSize: # print("here") # conn.close() # continue self.sockset.append(conn) UserLib.UpConn_map.append([conn,conn.getpeername(),0,'choked','uninterested',False,0,0,0]) elif s == sys.stdin: ##command = s.readline() ##if command == 'quit\n': UserDefs.Run=False break #otherwise there are data in socket of an established connection. else: #find position of current socket into uploading connections map try: ind=[ temp[0]==s for temp in UserLib.UpConn_map].index(True) except ValueError as detail: print("Unable to index connection at server 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.UpConn_map) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("2. ConnectionResetedByPeer at Server Thread:") UserLib.SocketLock.release() self.unchoke() continue except Exception as detail: print("2. Unexpected exception at Server Thread:",detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() try: msgtype = self.msg_r['type'] except Exception as detail: print("Key error at Server Thread:",detail) self.unchoke() continue #if message is a "block request" if msgtype == 'request': #create and send response via socket s. try: self.block(self.msg_r) UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.UpConn_map,self.msg) UserLib.UpConn_map[ind][7]+=1 #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("3. Unexpected exception at Server Thread:",detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() #if message is a "handshake request" elif msgtype == 'handshake': #check file id of requested file. #Connection should be closed if not self.msg_r['metadata_hash'] == UserLib.metadata_hash : print("Unable to seed requested file") s.close() del UserLib.UpConn_map[ind] continue #response including peer id of current peer. try: self.handshake_response() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.UpConn_map,self.msg) #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("4. Unexpected exception at Server Thread:",detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() #send bitmap to remote peer. try: self.bitfield() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.UpConn_map,self.msg) #Uppon Exception socket indexed by ind had been removed from "send_msg". except Exception as detail: print("5. Unexpected exception at Server Thread:",detail) UserLib.SocketLock.release() self.unchoke() continue else: UserLib.SocketLock.release() UserLib.UpConn_map[ind][5]=True try: print('\nNew Leecher:',s.getpeername(),"#accepted connections:",len(UserLib.UpConn_map)," ",time.time()) except Exception as detail: print("5.1 Unexpected exception at Server Thread:",detail) pass #and add peer identifier after a successful handshake. UserLib.UpConn_map[ind][2]=self.msg_r['peer_id'] elif msgtype == 'interested': UserLib.UpConn_map[ind][4]='interested' if UserLib.UpConn_map[ind][5]=='unchoked': self.unchoke() if self.unchokeinvoked == 0: self.unchoke() self.unchokeinvoked=1 elif msgtype == 'uninterested': UserLib.UpConn_map[ind][4]='uninterested' if UserLib.UpConn_map[ind][3]=='unchoked': self.unchoke() #acknowledgment received. elif msgtype == 'have': UserLib.UpConn_map[ind][6]=self.msg_r['interested'] #iii=[] #for i in range(0,len(UserLib.UpConn_map)): # if UserLib.UpConn_map[i][4]=='interested': # iii.append(UserLib.UpConn_map[i][6]) #print("iii:",iii) continue #unexpected message. else: print('Unexpected message type:',msgtype) continue #make "clean up" job. self.terminate() return
def unchoke(self): #reset timer self.timer.cancel() ##if there are active connections to your uploading set cancel and reset unchoke. if not UserLib.UpConn_map: self.unchokeflag=0 self.unchokeinvoked=0 return UserLib.SocketLock.acquire() if self.mode == 'seed': suggestedOpt=-1 mymin=10000 #remote peers (downloaders) that were recently (less than 20 seconds) unchoked remotedownloaders1=[] #rest of remote peer remotedownloaders2=[] curtime=time.time() for i in range(0,len(UserLib.UpConn_map)): unchoketime=UserLib.UpConn_map[i][8] if curtime-unchoketime<UserDefs.RecentUnchokeInterval: remotedownloaders1.append([unchoketime,i]) else: remotedownloaders2.append([UserLib.UpConn_map[i][7],i]) if UserLib.UpConn_map[i][6]<mymin: mymin=UserLib.UpConn_map[i][6] suggestedOpt=[0,i] remotedownloaders1.sort(reverse=True) remotedownloaders2.sort(reverse=True) remotedownloaders=remotedownloaders1+remotedownloaders2 if self.unchokeflag in [0,1]: if time.time()-self.lastunchoketime>=3*UserDefs.UnchokeInterval: self.lastunchoketime=time.time() if self.choice == 'optimistic': self.plannedOpt=random.choice(remotedownloaders) elif self.choice == 'optimal': self.plannedOpt=suggestedOpt try: peerpos=self.plannedOpt[1] UserLib.UpConn_map[peerpos][3]='unchoked' SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,{'type':'unchoke','mode':'opt'}) UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>::1.Unexpected exception: ",detail) for i in range(0,len(remotedownloaders)): peerpos=remotedownloaders[i][1] if not self.plannedOpt: continue elif self.plannedOpt[1]==remotedownloaders[i][1]: continue if i<UserDefs.RegularUnchokedNum: try: UserLib.UpConn_map[peerpos][3]='unchoked' except Exception as detail: print("<unchoke>:: 2.Unexpected exception:",detail) continue msg={'type':'unchoke','mode':'reg'} else: try: UserLib.UpConn_map[peerpos][3]='choked' except Exception as detail: print("<unchoke>:: 2.Unexpected exception:",detail) continue msg={'type':'choke'} try: SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,msg) if msg['type'] == 'unchoke': UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ",detail) continue else: for i in range(0,len(remotedownloaders)): peerpos=remotedownloaders[i][1] if i<UserDefs.RegularUnchokedNum+1: #print("296:",peerpos,len(UserLib.UpConn_map)) try: UserLib.UpConn_map[peerpos][3]='unchoked' except Exception as detail: print("<unchoke>:: 3.Unexpected exception:",detail) continue msg={'type':'unchoke','mode':'reg'} else: try: UserLib.UpConn_map[peerpos][3]='choked' except Exception as detail: print("<unchoke>:: 4.Unexpected exception:",detail) continue msg={'type':'choke'} try: SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,msg) if msg['type'] == 'unchoke': UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ",detail) continue #####--------------- else: interestedpeers=[] remoteuploaders=[] suggestedOpt=-1 mymin=10000 for i in range(0,len(UserLib.UpConn_map)): #for all remote peers (downloaders) that are interested to your content if UserLib.UpConn_map[i][4]=='interested': #keep their peer identifier peerid=UserLib.UpConn_map[i][2] interestedpeers.append([0,peerid,i]) if UserLib.UpConn_map[i][6]<mymin: mymin=UserLib.UpConn_map[i][6] suggestedOpt=[0,peerid,i] #and if they are also uploaders to you if peerid in [ s[4] for s in UserLib.DownConn_map ]: #find their position in the map of your downloaders peerpos=[ peerid==s[4] for s in UserLib.DownConn_map].index(True) #and for everyone that have send you at least one block at the last 30 seconds if UserLib.DownConn_map[peerpos][2]>0 and time.time()-UserLib.DownConn_map[peerpos][8]<3*UserDefs.UnchokeInterval: #keep position in uploading map, their peer id and number of blocks having sent to you. remoteuploaders.append([UserLib.DownConn_map[peerpos][2],peerid,i]) if len(interestedpeers)>0: if self.unchokeflag==0 and time.time()-self.lastunchoketime>=3*UserDefs.UnchokeInterval: self.lastunchoketime=time.time() if self.choice == 'optimistic': self.plannedOpt=random.choice(interestedpeers) elif self.choice == 'optimal': self.plannedOpt=suggestedOpt msg={'type':'unchoke','mode':'opt'} #print("1-->",self.plannedOpt,interestedpeers) #print("Opt unchoke",peerpos); try: peerpos=self.plannedOpt[2] UserLib.UpConn_map[peerpos][3]='unchoked' SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,msg) UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>:: 5.Unexpected exception: ",detail) #remote uploaders consists of [#blocks received, peerid, position at map of uploaders] for every remote uploader. remoteuploaders.sort(reverse=True) regularunchoked=[] if not remoteuploaders: regularunchoked=[] elif len(remoteuploaders)<=UserDefs.RegularUnchokedNum: regularunchoked=remoteuploaders else: for i in range(0,UserDefs.RegularUnchokedNum): regularunchoked.append(remoteuploaders[i]) #print("remote uploaders:",remoteuploaders) #print("The three fastest peers(Regular Unchoked) are:",regularunchoked) #print("planned optimistic unchoked:",self.plannedOpt) #print("2-->",self.plannedOpt) for i in range(0,len(remoteuploaders)): if remoteuploaders[i] == self.plannedOpt: continue try: peerpos=remoteuploaders[i][2] if remoteuploaders[i] in regularunchoked: msg={'type':'unchoke','mode':'reg'} UserLib.UpConn_map[peerpos][3]='unchoked' else: msg={'type':'choke'} UserLib.UpConn_map[peerpos][3]='choked' except IndexError: continue try: SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,msg) if msg['type']=='unchoke': UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ",detail) continue if not self.plannedOpt: pass elif self.plannedOpt[1] in [ s[1] for s in regularunchoked ]: while True: peerpos=random.randint(0,len(UserLib.UpConn_map)-1) peerid=UserLib.UpConn_map[peerpos][2] self.plannedOpt=[0,peerid,peerpos] msg={'type':'unchoke','mode':'reg'} UserLib.UpConn_map[peerpos][3]='unchoked' try: SocketLevel.send_msg(peerpos,-1,UserLib.UpConn_map,msg) UserLib.UpConn_map[peerpos][8]=time.time() except Exception as detail: print("<unchoke>:: Unexpected exception: ",detail) continue if UserLib.UpConn_map[peerpos][4] == 'interested': break UserLib.SocketLock.release() #if thread has not terminated if UserDefs.Run: self.timer=threading.Timer(UserDefs.UnchokeInterval,self.unchoke) self.timer.start() self.unchokeflag=(self.unchokeflag+1)%3