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 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