def block(self, connection_ind, msg): #IF BLOCK IF FOUND THIS WILL BE REMOVED #and it is not corrupted, try to write it to #the respective position in file,]. l = -1 for s in UserLib.requests: if s[0] == msg['chunkpos']: l = 0 UserLib.requests.remove(s) break if l == -1 or bitmap.bmp_isvalid(UserLib.bmp, msg['chunkpos'], UserLib.lock): raise UserLib.UnexpectedBlock if mysha1lib.mysha1( msg['chunk']) == UserLib.sha1s_map[msg['chunkpos']]: try: self.f.seek(int(msg['chunkpos']) * UserDefs.PieceSize) self.f.write(msg['chunk']) #if an Exception occurs close file stream and raise it. except IOError as detail: print("<block>:: File Error at Leecher thread:", detail) self.f.close() raise #if an Exception occurs close file stream and raise it. except Exception as detail: print("<block>:: Unexpected Exception :", detail) self.f.close() raise try: # mutual exclusion before informing bitmap. bitmap.bmp_setvalid(UserLib.bmp, msg['chunkpos'], UserLib.lock) except Exception as detail: print("<block>:: Unexpected Exception while setting bitmap:", detail) raise # increase chunks downloaded from current connection. UserLib.DownConn_map[connection_ind][2] += 1 UserLib.DownConn_map[connection_ind][8] = time.time() # inclease total chunks downloaded. UserLib.PiecesDownloaded += 1 sys.stderr.flush() sys.stderr.write( "%.2f%%\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" % (100 * UserLib.PiecesDownloaded / UserLib.BMPLENGTH)) else: print("Received corrupted block") raise UserLib.BlockCorrupted
def block(self,connection_ind,msg): #IF BLOCK IF FOUND THIS WILL BE REMOVED #and it is not corrupted, try to write it to #the respective position in file,]. l=-1 for s in UserLib.requests: if s[0] == msg['chunkpos']: l=0 UserLib.requests.remove(s) break if l == -1 or bitmap.bmp_isvalid(UserLib.bmp,msg['chunkpos'],UserLib.lock) : raise UserLib.UnexpectedBlock if mysha1lib.mysha1(msg['chunk'])==UserLib.sha1s_map[msg['chunkpos']]: try: self.f.seek(int(msg['chunkpos'])*UserDefs.PieceSize) self.f.write(msg['chunk']) #if an Exception occurs close file stream and raise it. except IOError as detail: print("<block>:: File Error at Leecher thread:",detail) self.f.close() raise #if an Exception occurs close file stream and raise it. except Exception as detail: print("<block>:: Unexpected Exception :",detail) self.f.close() raise try: # mutual exclusion before informing bitmap. bitmap.bmp_setvalid(UserLib.bmp,msg['chunkpos'],UserLib.lock) except Exception as detail: print("<block>:: Unexpected Exception while setting bitmap:",detail) raise # increase chunks downloaded from current connection. UserLib.DownConn_map[connection_ind][2]+=1 UserLib.DownConn_map[connection_ind][8]=time.time() # inclease total chunks downloaded. UserLib.PiecesDownloaded+=1 sys.stderr.flush() sys.stderr.write("%.2f%%\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"%(100*UserLib.PiecesDownloaded/UserLib.BMPLENGTH)) else: print("Received corrupted block") raise UserLib.BlockCorrupted
def run(self): print("my peer id:", UserLib.mypeerid) #keep beginning time self.begtime = time.time() random.seed(time.time()) #self.begtime) #try to open file to write received chunks. try: self.f = open(self.filename, 'wb') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError at Leecher thread:", detail) self.terminate() return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception in Leecher thread:", detail) self.terminate() return #while thread should not terminate. t = self.begtime while UserDefs.Run: #If there are no peers in peer set, new connections should be established. #THIS WILL BE DONE IF CONNECTIONS ARE LESS THAN A THREASHOLD. if time.time( ) - t > UserDefs.PeerListReqInterval or not UserLib.DownConn_map: t = time.time() if not UserLib.DownConn_map: print("Empty connections") try: self.establish_connections() except UserLib.EstablishConnError as detail: print("establish connections error at Leecher thread:", detail) time.sleep(UserDefs.PeerListReqInterval) continue except UserLib.TerminateThread: break except Exception as detail: print("2.Unexpected Exception in Leecher thread:", detail) time.sleep(UserDefs.PeerListReqInterval) continue #NOW WE HAVE AS MUCH AS MAXDOWNCONN established connections and tokens to send requests. #but connections are choked.So watch the set to receive unchoke messages. self.sockset = [temp[0] for temp in UserLib.DownConn_map] try: inputready, outputready, exceptionready = select.select( self.sockset, [], [], UserDefs.SelectTimeout) except (ValueError, select.error) as detail: print("Select Exception in Leecher thread:", detail) continue #1.) In case a descripitor from your set has data that is state oriented msg. for s in inputready: #find position of socket having data into downloading connections map try: ind = [temp[0] == s for temp in UserLib.DownConn_map].index(True) except ValueError as detail: print("Value Error at Leecher Thread:", detail, s) continue #try to receive message via socket indexed by ind. try: UserLib.SocketLock.acquire() self.msg_r = SocketLevel.recv_msg(ind, -1, UserLib.DownConn_map, True) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("3.ConnectionResetedByPeer in Leecher thread:") continue except Exception as detail: print("3.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() try: msgtype = self.msg_r['type'] except Exception as detail: print("4.Unexpected Exception in Leecher thread:", detail) continue if msgtype == 'unchoke': if self.unchokes == 0: print( "First unchoke after:%.2f" % (time.time() - self.begtime), "seconds") self.unchokes += 1 UserLib.DownConn_map[ind][5] = 'unchoked' elif msgtype == 'choke': UserLib.DownConn_map[ind][5] = 'choked' #delete pending requests to chocking remote peer. UserLib.requests = [ r for r in UserLib.requests if not r[1] == UserLib.DownConn_map[ind][4] ] elif msgtype == 'have': #update bitmap of peer having a new piece try: bitmap.bmp_setvalid(UserLib.DownConn_map[ind][3], self.msg_r['chunkno'], -1) #check if you are interested in this peer state = bitmap.interested(UserLib.bmp, UserLib.DownConn_map[ind][3], UserLib.BMPLENGTH, UserLib.lock) #if there is a change in your state about this peer except Exception: continue if UserLib.DownConn_map[ind][ 6] == 'uninterested' and state == 'interested': #inform your map UserLib.DownConn_map[ind][6] = state #inform remote peer try: self.interested() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("5.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() #if received message is "block respose" #try to write block to resective position in file.: elif msgtype == 'block': chunkno = self.msg_r['chunkpos'] try: self.block(ind, self.msg_r) #Exception indication requested block is not available #to peer last request was send. except UserLib.BlockCorrupted: print("6.BlockCorrupted in Leecher thread:") continue except UserLib.UnexpectedBlock: #print("6.UnexpectedBlock in Leecher thread:") continue #Uppon Exception Terminate thread except Exception as detail: print("6.Unexpected Exception in Leecher thread:", detail) continue self.have(chunkno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("7.1.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() i = len(UserLib.UpConn_map) - 1 UserLib.SocketLock.acquire() while i >= 0: try: if UserLib.DownConn_map[ind][ 4] == UserLib.UpConn_map[i][2]: i -= 1 continue except Exception as detail: i -= 1 print( "7.1.2.Unexpected Exception in Lecher thread:", detail, ind, UserLib.UpConn_map, UserLib.DownConn_map) continue #inform all downloaders directly conected to you that you #receive a new piece. try: #UserLib.SocketLock.acquire() SocketLevel.send_msg(i, -1, UserLib.UpConn_map, self.msg) except Exception as detail: i = len(UserLib.UpConn_map) - 1 print("7.2.Unexpected Exception in Lecher thread:", detail, i, len(UserLib.UpConn_map)) else: i -= 1 #finally: # UserLib.SocketLock.release() UserLib.SocketLock.release() for i in range(0, len(UserLib.DownConn_map)): try: state = bitmap.interested( UserLib.bmp, UserLib.DownConn_map[i][3], UserLib.BMPLENGTH, UserLib.lock) except Exception: continue if UserLib.DownConn_map[i][ 6] == 'interested' and state == 'uninterested': UserLib.DownConn_map[i][6] = state try: #print("here",UserLib.DownConn_map,UserLib.bmp) self.uninterested() UserLib.SocketLock.acquire() SocketLevel.send_msg(i, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print( "9.Unexpected Exception in Leecher thread:", detail) continue finally: UserLib.SocketLock.release() #select block and uploader. try: ind, self.blockno = self.select_block() except UserLib.FileCompletelyDownloaded: break except UserLib.AllConnectionsChoked: #print("11.AllConnectionsChoked or unintetresting in Leecher thread") continue except UserLib.MaxRequestsSent: #print("11.MaxRequestsSent in Leecher thread") continue except Exception as detail: print("11.Unexpected Exception in Leecher thread:", detail) break #if it is a pending block request, dont do anything. #prepare request for the selected block. self.request(self.blockno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind, -1, UserLib.DownConn_map, self.msg, True) except Exception as detail: print("12.Unexpected Exception in Leecher thread:", detail) continue else: UserLib.requests.append( [self.blockno, UserLib.DownConn_map[ind][4], 0]) finally: UserLib.SocketLock.release() #while Run #make "clen up" job and terminate thread. self.terminate() return
def run ( self ): print("my peer id:",UserLib.mypeerid) #keep beginning time self.begtime=time.time() random.seed(time.time())#self.begtime) #try to open file to write received chunks. try: self.f=open(self.filename,'wb') #Uppon Exception, make clen up job and terminatethread. except IOError as detail: print("IOError at Leecher thread:",detail) self.terminate() return #Uppon Exception, make clen up job and terminate thread. except Exception as detail: print("0.Unexpected exception in Leecher thread:",detail) self.terminate() return #while thread should not terminate. t=self.begtime while UserDefs.Run: #If there are no peers in peer set, new connections should be established. #THIS WILL BE DONE IF CONNECTIONS ARE LESS THAN A THREASHOLD. if time.time()-t > UserDefs.PeerListReqInterval or not UserLib.DownConn_map: t=time.time() if not UserLib.DownConn_map: print("Empty connections") try: self.establish_connections() except UserLib.EstablishConnError as detail: print("establish connections error at Leecher thread:",detail) time.sleep(UserDefs.PeerListReqInterval) continue except UserLib.TerminateThread: break except Exception as detail: print("2.Unexpected Exception in Leecher thread:",detail) time.sleep(UserDefs.PeerListReqInterval) continue #NOW WE HAVE AS MUCH AS MAXDOWNCONN established connections and tokens to send requests. #but connections are choked.So watch the set to receive unchoke messages. self.sockset=[ temp[0] for temp in UserLib.DownConn_map ] try: inputready, outputready, exceptionready = select.select(self.sockset,[],[],UserDefs.SelectTimeout) except (ValueError, select.error) as detail: print("Select Exception in Leecher thread:",detail) continue #1.) In case a descripitor from your set has data that is state oriented msg. for s in inputready: #find position of socket having data into downloading connections map try: ind=[ temp[0]==s for temp in UserLib.DownConn_map].index(True) except ValueError as detail: print("Value Error at Leecher Thread:",detail,s) continue #try to receive message via socket indexed by ind. try: UserLib.SocketLock.acquire() self.msg_r=SocketLevel.recv_msg(ind, -1, UserLib.DownConn_map,True) #Uppon Exception socket indexed by ind had been removed from "recv_msg". except UserLib.ConnectionResetedByPeer: print("3.ConnectionResetedByPeer in Leecher thread:") continue except Exception as detail: print("3.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() try: msgtype=self.msg_r['type'] except Exception as detail: print("4.Unexpected Exception in Leecher thread:",detail) continue if msgtype == 'unchoke': if self.unchokes == 0: print("First unchoke after:%.2f"%(time.time()-self.begtime),"seconds") self.unchokes+=1 UserLib.DownConn_map[ind][5]='unchoked' elif msgtype == 'choke': UserLib.DownConn_map[ind][5]='choked' #delete pending requests to chocking remote peer. UserLib.requests=[ r for r in UserLib.requests if not r[1] == UserLib.DownConn_map[ind][4]] elif msgtype == 'have': #update bitmap of peer having a new piece try: bitmap.bmp_setvalid(UserLib.DownConn_map[ind][3],self.msg_r['chunkno'],-1) #check if you are interested in this peer state=bitmap.interested(UserLib.bmp,UserLib.DownConn_map[ind][3],UserLib.BMPLENGTH,UserLib.lock) #if there is a change in your state about this peer except Exception: continue if UserLib.DownConn_map[ind][6]== 'uninterested' and state=='interested': #inform your map UserLib.DownConn_map[ind][6]=state #inform remote peer try: self.interested() UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("5.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() #if received message is "block respose" #try to write block to resective position in file.: elif msgtype == 'block': chunkno=self.msg_r['chunkpos'] try: self.block(ind,self.msg_r) #Exception indication requested block is not available #to peer last request was send. except UserLib.BlockCorrupted: print("6.BlockCorrupted in Leecher thread:") continue except UserLib.UnexpectedBlock: #print("6.UnexpectedBlock in Leecher thread:") continue #Uppon Exception Terminate thread except Exception as detail: print("6.Unexpected Exception in Leecher thread:",detail) continue self.have(chunkno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("7.1.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() i=len(UserLib.UpConn_map)-1 UserLib.SocketLock.acquire() while i >=0: try: if UserLib.DownConn_map[ind][4]==UserLib.UpConn_map[i][2]: i-=1 continue except Exception as detail: i-=1 print("7.1.2.Unexpected Exception in Lecher thread:",detail,ind,UserLib.UpConn_map,UserLib.DownConn_map) continue #inform all downloaders directly conected to you that you #receive a new piece. try: #UserLib.SocketLock.acquire() SocketLevel.send_msg(i,-1,UserLib.UpConn_map,self.msg) except Exception as detail: i=len(UserLib.UpConn_map)-1 print("7.2.Unexpected Exception in Lecher thread:",detail,i,len(UserLib.UpConn_map)) else: i-=1 #finally: # UserLib.SocketLock.release() UserLib.SocketLock.release() for i in range(0,len(UserLib.DownConn_map)): try: state=bitmap.interested(UserLib.bmp,UserLib.DownConn_map[i][3],UserLib.BMPLENGTH,UserLib.lock) except Exception: continue if UserLib.DownConn_map[i][6]=='interested' and state=='uninterested': UserLib.DownConn_map[i][6]=state try: #print("here",UserLib.DownConn_map,UserLib.bmp) self.uninterested() UserLib.SocketLock.acquire() SocketLevel.send_msg(i,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("9.Unexpected Exception in Leecher thread:",detail) continue finally: UserLib.SocketLock.release() #select block and uploader. try: ind, self.blockno =self.select_block() except UserLib.FileCompletelyDownloaded: break except UserLib.AllConnectionsChoked: #print("11.AllConnectionsChoked or unintetresting in Leecher thread") continue except UserLib.MaxRequestsSent: #print("11.MaxRequestsSent in Leecher thread") continue except Exception as detail: print("11.Unexpected Exception in Leecher thread:",detail) break #if it is a pending block request, dont do anything. #prepare request for the selected block. self.request(self.blockno) try: UserLib.SocketLock.acquire() SocketLevel.send_msg(ind,-1,UserLib.DownConn_map,self.msg,True) except Exception as detail: print("12.Unexpected Exception in Leecher thread:",detail) continue else: UserLib.requests.append([self.blockno,UserLib.DownConn_map[ind][4],0]) finally: UserLib.SocketLock.release() #while Run #make "clen up" job and terminate thread. self.terminate() return