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

	#try to create a socket and send a TCP connection request to each peer of the set.
	try:
		newsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
		newsock.connect ((listeningips[i], listeningports[i]))
	#Uppon Exception close recently created socket and raise Exception.
	except socket.error:
		print("<establish_connection>:: Socket Error Unable to establish connection with peer at port:",listeningports[i])
		newsock.close()
		raise
	#Uppon Exception close recently created socket and raise Exception.
	except Exception as detail:
		print("<establish_connection>:: Unexpected exception Unable to establish connection with peer at port:",listeningports[i],":",detail)
		newsock.close()
		raise
	#Uppon success, append to connections map a tuple containing (socket, port, 
	#counter of blocks received, bitmap, peerid, and state info) of recently 
	#established connection.
	connections.append([newsock,listeningports[i],0,[],0,'choked','',listeningips[i],0])
	#create and send handshake message
	msg={'type':'handshake'
		,'metadata_hash':UserLib.metadata_hash
		,'peer_id':UserLib.mypeerid
	}
	try:
		SocketLevel.send_msg(len(connections)-1,-1,connections,msg, True)
	except Exception as detail: 
		print("<establish_connection>:: 1.Unable to establish connection with peer at port:",listeningports[i],":",detail)
		raise
	#receive handshake response
	try:	
		msg_r=SocketLevel.recv_msg(len(connections)-1, -1, connections, True)
	except Exception as detail:  
		print("<establish_connection>:: 2.Unable to establish connection with peer at port:",listeningports[i],":",detail)
		raise
	else:	
		#if not a handshake response received, ro peed id received is not valid.	
		if not msg_r['type'] == 'handshake_response' or not msg_r['peerid'] in peerids:
			print("------------------------>",msg_r)
			newsock.close()
			#remove socket from connections map.
			del connections[-1]
			raise UserLib.UnexpectedMessage
		else:	
			#keep peer id from last message.
			peerid=msg_r['peerid']
			#receive bitmap of recently appened peer.
			try:	
				msg_r=SocketLevel.recv_msg(len(connections)-1, -1, connections,True)
			except Exception as detail:  
				print("<establish_connection>:: 4.Unable to establish connection with peer at port:",listeningports[i],":",detail)
				raise
			if not msg_r['type'] == 'bitfield':
				newsock.close()
				#remove socket from connections map.
				del connections[-1]
				raise UserLib.UnexpectedMessage
			connections[-1][3]=msg_r['bmp']   
			connections[-1][4]=peerid
			#check if u are interested in blocks of this remote peer or not.
			try:
				connections[-1][6]=bitmap.interested(UserLib.bmp,msg_r['bmp'],msg_r['bmplen'],UserLib.lock)
			except Exception as detail:
				print("<establish_connection>:: 5.Unable to establish connection with peer at port:",listeningports[i],":",detail)
				#remove socket from connections map.
				del connections[-1]
				raise
			if connections[-1][6]=='uninterested':
				msg={'type':'uninterested'}	
			else:
				msg={'type':'interested'}
			#inform this remote peer if interested or not.
			try:
				SocketLevel.send_msg(len(connections)-1,-1,connections,msg,True)
			except Exception as detail: 
				print("<establish_connection>:: 6.Unable to establish connection with peer at port:",listeningports[i],":",detail)
				raise