def __init__(self, cwd): self.__cwd = cwd # current working directory self.__BootedasUser = True self.__tcpTracSock = Mytcpsocket() self.__tcpListenSock = Mytcpsocket() self.__MaxNumConn = MAX_PEER_CONNECTION self.__Addr = (([ ip for ip in gethostbyname_ex(gethostname())[2] if not ip.startswith("127.") ][0]), choice(range(50000, 60000))) self.__tcpCliSockets = [] self.__ServerNeighborhood = [] self.__ServerConnectionIPs = [] self.__ServerConnectionSocks = [] self.__NumofConnections = 0 self.__ExcludedServerAddr = [] self.__choketimer = 30 self.__StartWaiting = False self.__receivedFile = None # streaming file object self.__avaiMovieList = {} # available movie list from the tracker self.__movieHashNames = {} self.__currentvid = 'None' # current video that is being watched self.__NumofChunks = 0 self.__NumofLeftPieces = 0 self.__neighborLock = thread.allocate_lock( ) # lock for the neighborhood update self.__connectionLock = thread.allocate_lock() self.__timerLock = thread.allocate_lock() self.__streamingStatLock = thread.allocate_lock() self.__bufferStatLock = thread.allocate_lock() self.__emptyAvailable = threading.Event() self.__emptyAvailable.clear() # one of the download chunks is waiting for other corresponding threads to finish that chunk self.__DownloadWait = threading.Event() self.__DownloadWait.clear() # wait till download is finished self.__BufferFullWait = threading.Event() self.__BufferFullWait.clear() # buffer too much, wait before download self.__BufferEmptyWait = threading.Event() self.__BufferEmptyWait.clear() # buffer not enough, download from server self.__streamingWait = threading.Event() self.__streamingWait.clear() # wait till buffer is ready to stream self.__downloadthreads = [] self.__EXIT = False
def __Connect2Client(self, number): self.__connectionLock.acquire() self.__neighborLock.acquire() Neighborhood = lminus(self.__ClientNeighborhood, self.__ClientConnectionIPs) potentialconnect = sample(Neighborhood, min(len(Neighborhood), number)) for eachClient in potentialconnect: if self.__NumofConnections < self.__MaxNumConn: if eachClient not in self.__ClientConnectionIPs: cliSock = Mytcpsocket() ack1 = cliSock.Connect2Server(eachClient) ack2 = cliSock.sendmsg(self.__Addr[1]) ack3 = cliSock.recvmsg(BUFSIZ) # receive ACK if ack1 and ack2 and ack3 != 'closed': self.__NumofConnections += 1 self.__ClientConnectionSocks.append(cliSock) self.__ClientConnectionIPs.append(eachClient) t = MyThread(self.__upload, (cliSock, eachClient), self.__upload.__name__) self.__UploadThreadsLock.acquire() self.__UploadThreads.append(t) self.__UploadThreadsLock.release() self.__BWControlBoot.set() # start BW control self.__RateAllocBoot.set() # start rate allocation t.start() sleep(PROCESS_TIME) else: self.__ClientNeighborhood.remove(eachClient) else: break self.__connectionLock.release() self.__neighborLock.release()
def __Connect2Server(self, *targs): args = targs[0] number = args[0] videohash = args[1] self.__connectionLock.acquire() self.__neighborLock.acquire() Neighborhood = lminus(self.__ServerNeighborhood, self.__ServerConnectionIPs) potentialconnect = sample(Neighborhood, min(len(Neighborhood), number)) for eachServer in potentialconnect: if self.__NumofConnections < self.__MaxNumConn: if eachServer not in self.__ServerConnectionIPs: servSock = Mytcpsocket() ack1 = servSock.Connect2Server(eachServer) ack2 = servSock.sendmsg(self.__Addr[1]) ack3 = servSock.recvmsg(BUFSIZ) # receive ACK if ack1 and ack2 and ack3 != 'closed': self.__NumofConnections += 1 self.__ServerConnectionSocks.append(servSock) self.__ServerConnectionIPs.append(eachServer) t = MyThread(self.__download, (servSock, eachServer, videohash), self.__download.__name__) t.start() sleep(PROCESS_TIME) self.__downloadthreads.append(t) else: self.__ServerNeighborhood.remove(eachServer) else: break self.__connectionLock.release() self.__neighborLock.release()
def __WaitforConnection(self, *targs): self.__tcpListenSock.InitServSock(self.__Addr, self.__MaxNumConn) while True: if self.__EXIT: return (tcpServSock, SERVER_ADDR) = self.__tcpListenSock.WaitforConn() self.__connectionLock.acquire() servtcpsock = Mytcpsocket(tcpServSock) if self.__NumofConnections < self.__MaxNumConn: servport = servtcpsock.recvmsg(BUFSIZ) ack = servtcpsock.sendmsg('ACK') # send ACK SERVER_SERV_ADDR = (SERVER_ADDR[0], servport) if ((SERVER_SERV_ADDR in self.__ServerConnectionIPs) or (SERVER_SERV_ADDR == self.__ExcludedServerAddr) or (not ack) or servport == 'closed'): servtcpsock.close() else: self.__ServerConnectionSocks.append(servtcpsock) self.__ServerConnectionIPs.append(SERVER_SERV_ADDR) self.__NumofConnections += 1 if VERBOSE: print "...connected from:", SERVER_SERV_ADDR t = MyThread( self.__download, (servtcpsock, SERVER_SERV_ADDR, self.__currentvid), self.__download.__name__) t.start() sleep(PROCESS_TIME) self.__downloadthreads.append(t) else: servtcpsock.close( ) # close if the number of connections exceeds max self.__connectionLock.release()
def __init__(self, Tracker_Addr=TRACKER_ADDRESS): self.__socket = Mytcpsocket() # a new socket self.__Addr = Tracker_Addr # IP address + port self.__MaxNumConn = MAX_TRAC_CONNECTION self.__userDict = {} # connecting addresses of active (estimate) users self.__servDict = { } # connecting addresses of active (estimate) helpers #self.__servDict[MEDIA_SERVER_ADDRESS] = 1 # the central server self.__inputLock = thread.allocate_lock( ) # lock for the input variables self.__EXIT = 0 # exit the system or not self.__movieList = {} # list of movie names
def __commtotracker(self, *targs): ack = False while not ack: ack = self.__tcpTracSock.Connect2Server(TRACKER_ADDRESS) if ack: countdown = 0 while True: if countdown == 0: ack = self.__tcpTracSock.sendmsg('serv+' + repr(self.__Addr[1])) newneighborhood = self.__tcpTracSock.recvmsg(BUFSIZ) avaiMovieList = self.__tcpTracSock.recvmsg(BUFSIZ) if ( not ack ) or newneighborhood == 'closed' or avaiMovieList == 'closed': ack = False break ACK = 'ACK' if self.__isserver: movienames = "" for fhash, fname in self.__movieList.iteritems(): movienames = (movienames + '+' + fname + '#' + self.__videoStat[fhash][0] + '#' + self.__videoStat[fhash][1]) ack = self.__tcpTracSock.sendmsg('list' + movienames) ACK = self.__tcpTracSock.recvmsg(BUFSIZ) if (not ack) or ACK == 'closed': ack = False break else: del self.__videoStat self.__videoStat = {} for eachmovie in avaiMovieList.keys(): self.__videoStat[hashlib.md5( eachmovie).hexdigest( )] = avaiMovieList[eachmovie] self.__neighborLock.acquire() self.__ClientNeighborhood = union( self.__ClientNeighborhood, newneighborhood) ## might have to set a maximum limit of neighborhood ## self.__neighborLock.release() countdown = OBTAIN_NEIGHBOR_PERIOD / INTERVAL_TRACKER_COMMUNICATION else: ack = self.__tcpTracSock.sendmsg('alive') if not ack: break sleep(INTERVAL_TRACKER_COMMUNICATION) countdown -= 1 sleep(TRY_INTERVAL) del self.__tcpTracSock self.__tcpTracSock = Mytcpsocket()
def __commtotracker(self, *targs): ack = False while not ack: if self.__EXIT: return ack = self.__tcpTracSock.Connect2Server(TRACKER_ADDRESS) #print TRACKER_ADDRESS if ack: countdown = 0 while True: if self.__EXIT: return if countdown == 0: ack = self.__tcpTracSock.sendmsg('user+' + repr(self.__Addr[1])) newneighborhood = self.__tcpTracSock.recvmsg(BUFSIZ) self.__avaiMovieList = self.__tcpTracSock.recvmsg( BUFSIZ) if ( not ack ) or newneighborhood == 'closed' or self.__avaiMovieList == 'closed': ack = False break del self.__movieHashNames self.__movieHashNames = {} for eachmovie in self.__avaiMovieList.keys(): self.__movieHashNames[hashlib.md5( eachmovie).hexdigest( )] = self.__avaiMovieList[eachmovie] self.__neighborLock.acquire() ## might have to set a maximum limit of neighborhood ## self.__ServerNeighborhood = union( self.__ServerNeighborhood, newneighborhood) self.__ServerNeighborhood = lminus( self.__ServerNeighborhood, self.__ExcludedServerAddr) self.__neighborLock.release() countdown = OBTAIN_NEIGHBOR_PERIOD / INTERVAL_TRACKER_COMMUNICATION else: ack = self.__tcpTracSock.sendmsg('alive') if not ack: break sleep(INTERVAL_TRACKER_COMMUNICATION) countdown -= 1 # send alive msg interval sleep(TRY_INTERVAL) # obtain neighborhood/movielist interval del self.__tcpTracSock self.__tcpTracSock = Mytcpsocket()
def __registerpeer( self, *targs ): # register the peer and obtain a list of potential neighbors args = targs[0] CliSocket = args[0] CliAddr = args[1] myClisock = Mytcpsocket(CliSocket) IS_SERV = -1 while True: data = myClisock.recvmsg(BUFSIZ) if 'serv' in str.lower(data): IS_SERV = 1 CliAddr = (CliAddr[0], int(data.split('+')[1])) self.__servDict[CliAddr] = 1 pc = self.__potentialconn( CliAddr, self.__userDict ) # return a list of user addresses \ itself myClisock.sendmsg(pc) myClisock.sendmsg(self.__movieList) # send movie list to watch elif 'user' in str.lower(data): IS_SERV = 0 CliAddr = (CliAddr[0], int(data.split('+')[1])) self.__userDict[CliAddr] = 1 pc = self.__potentialconn( CliAddr, self.__servDict ) # return a list of serv addresses \ itself myClisock.sendmsg(pc) myClisock.sendmsg(self.__movieList) # send movie list to watch elif 'list' in str.lower(data): data = data.split('+') for i in range(1, len(data)): videostat = data[i].split('#') self.__movieList[videostat[0]] = [ int(videostat[1]), int(videostat[2]) ] myClisock.sendmsg('ACK') elif str.lower(data) == 'alive': # still alive print data, ' from ', CliAddr pass else: if IS_SERV == 1: self.__servDict.pop(CliAddr) elif IS_SERV == 0: self.__userDict.pop(CliAddr) myClisock.close() # close the connection break
def __WaitforConnection(self, *targs): self.__tcpSerSock.InitServSock(self.__Addr, self.__MaxNumConn) if VERBOSE: print "Waiting for connection..." while True: (tcpClientSock, CLIENT_ADDR) = self.__tcpSerSock.WaitforConn() self.__connectionLock.acquire() clitcpsock = Mytcpsocket(tcpClientSock) if self.__NumofConnections < self.__MaxNumConn: servport = clitcpsock.recvmsg(BUFSIZ) ack = clitcpsock.sendmsg('ACK') CLIENT_SERV_ADDR = (CLIENT_ADDR[0], servport) if ((CLIENT_SERV_ADDR in self.__ClientConnectionIPs) or (not ack) or servport == 'closed'): clitcpsock.close() else: self.__ClientConnectionSocks.append(clitcpsock) self.__ClientConnectionIPs.append(CLIENT_SERV_ADDR) self.__NumofConnections += 1 if VERBOSE: print "...connected from:", CLIENT_ADDR t = MyThread(self.__upload, (clitcpsock, CLIENT_SERV_ADDR), self.__upload.__name__) self.__UploadThreadsLock.acquire() self.__UploadThreads.append(t) self.__UploadThreadsLock.release() self.__BWControlBoot.set() # start BW control self.__RateAllocBoot.set() # start rate allocation t.start() sleep(PROCESS_TIME) else: clitcpsock.close( ) # close if the number of connections exceeds max self.__connectionLock.release()
def __init__(self, cwd, IS_SERVER=1): self.__cwd = cwd # current working directory self.__isserver = IS_SERVER # I mean the True server, not helper self.__tcpSerSock = Mytcpsocket() # initiate server socket self.__tcpTracSock = Mytcpsocket() # initiate tracker socket self.__PATH = self.__cwd + os.sep + SERVER_PATH + os.sep # set up video caching directory if not os.path.exists(self.__PATH): os.makedirs(self.__PATH) # movieList: vhash: vname; videoDict: vhash: vpath; videoStat: vhash: [NumofChunks, NumofLeftOverPieces] self.__movieList = {} self.__videoDict = {} self.__videoStat = {} # storeAlloc: vhash: vsize; storePrices: vhash: vprice self.__storeAlloc = {} self.__storePrices = {} # mediaReaders: vhash: [a list of open file readers for vhash]; mediaUpdaters: vhash: file writer self.__mediaReaders = {} self.__mediaUpdaters = {} if IS_SERVER: self.__MaxNumConn = MAX_SERV_CONNECTION self.__Addr = MEDIA_SERVER_ADDRESS # read all the movies and convert newly added movies f = open(self.__PATH + 'movielist.txt', 'r+') allLines = f.readlines() f.close() for eachmovie in allLines: moviename = eachmovie.split('\n')[0] self.__movieList[hashlib.md5( moviename).hexdigest()] = moviename #vhash: vname dirList = os.listdir(self.__PATH) for dname in dirList: if ( not os.path.isdir(self.__PATH + dname) ) and dname != 'movielist.txt': # if video not converted, convert hashname = hashlib.md5(dname.split('.')[0]).hexdigest() if (hashname in self.__movieList and not hashname in dirList): videopath = self.__PATH + hashname os.makedirs(videopath) self.__convertVideo(videopath + os.sep, self.__PATH + dname) # convert the video dirList = os.listdir(self.__PATH) for dname in dirList: if os.path.isdir(self.__PATH + dname): videopath = self.__PATH + dname + os.sep if dname in self.__movieList: self.__videoDict[dname] = videopath # vhash: vpath f = open(videopath + 'length', 'rb') dt = f.readlines() self.__videoStat[dname] = dt[0].split(',') # vhash: [NumofChunks, NumofLeftoverPieces] self.__mediaReaders[dname] = [] else: print videopath # not in list, to be deleted shutil.rmtree(videopath) else: self.__MaxNumConn = MAX_PEER_CONNECTION # need to implement NAT traversal ##########start here############ self.__Addr = (([ ip for ip in gethostbyname_ex(gethostname())[2] if not ip.startswith("127.") ][0]), choice(range(50000, 60000))) ##########end here############ dirList = os.listdir(self.__PATH) for dname in dirList: if os.path.isdir(self.__PATH + dname): videopath = self.__PATH + dname + os.sep self.__videoDict[dname] = videopath self.__mediaReaders[dname] = [] self.__mediaUpdaters[dname] = MediaFileWrapper( videopath, False) # write access self.__storeAlloc[dname] = 0 self.__storePrices[dname] = 0 self.__ClientNeighborhood = [] self.__NumofConnections = 0 self.__ClientConnectionIPs = [] self.__ClientConnectionSocks = [] self.__choketimer = 30 self.__uploadBW = 0 # KB/sec self.__uploadedBytes = 0 # uploaded bytes in a second self.__UploadThreads = [ ] # upload threads. used to control UploadBWControl self.__neighborLock = thread.allocate_lock() self.__connectionLock = thread.allocate_lock() self.__timerLock = thread.allocate_lock() self.__rateAllocLock = thread.allocate_lock() self.__mediaReaderLock = thread.allocate_lock() self.__uploadStatLock = thread.allocate_lock() self.__UploadThreadsLock = thread.allocate_lock() self.__BWControlBoot = threading.Event() self.__BWControlBoot.clear() # we don't need BW control all the time self.__uploadBWExceed = threading.Event() self.__uploadBWExceed.clear() self.__RateAllocBoot = threading.Event() self.__RateAllocBoot.clear()