def connectionResponse(self, datagram, packet, host_port): packet = Packet(0, 0, 0, 0) packet.unpackHeader(datagram) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack( format, datagram) userName = packet.data[1].decode("utf-8") if self.serverProxy.userExists(userName): #num seq a traiter #todo self.expected_num_seq[host_port] = 1 self.num_seq[host_port] = 0 self.sent_packet_history[host_port] = {} self.received_packet_history[host_port] = {} self.failed(host_port) self.errorDict[host_port] = "userExists" elif self.malformed(userName, user_name=True) == True: self.expected_num_seq[host_port] = 1 self.num_seq[host_port] = 0 self.sent_packet_history[host_port] = {} self.received_packet_history[host_port] = {} self.failed(host_port) self.errorDict[host_port] = "malformed User Name" elif len(self.serverProxy.getUserList()) >= 513: self.expected_num_seq[host_port] = 1 self.num_seq[host_port] = 0 self.sent_packet_history[host_port] = {} self.received_packet_history[host_port] = {} self.failed(host_port) self.errorDict[host_port] = "serverSaturated" else: self.expected_num_seq[userName] = 1 self.num_seq[userName] = 0 self.sent_packet_history[userName] = {} self.received_packet_history[userName] = {} self.serverProxy.addUser(userName, ROOM_IDS.MAIN_ROOM, None, host_port) self.movieRoom[userName] = ROOM_IDS.MAIN_ROOM connectionDone = Packet(1, self.num_seq[userName], 0, '') self.sendPacket(connectionDone, host_port) #????? self.serverProxy.updateUserChatroom(userName, ROOM_IDS.MAIN_ROOM)
def errorReceived(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) print("ERREUR", packet.data[1].decode("utf8")) if 'wrongNumSeq:' in packet.data[1].decode('utf8'): self.num_seq = int(packet.data[1][12:].decode("utf8")) print("new num seq", self.num_seq) print("error :", packet.data[1].decode("utf8")) return 0
def errorReceived(self, datagram, user_name): packet = Packet(0, 0, 0, 0) packet.unpackHeader(datagram) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack( format, datagram) if 'wrongNumSeq:' in packet.data[1].decode('utf8'): self.num_seq[user_name] = int(packet.data[1][12:].decode("utf8")) print("error :", packet.data[1].decode("utf8")) return 0
def errorReceived(self,datagram): packet = Packet(0, 0, 0, 0) packet.unpackHeader(datagram) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, datagram) if packet.data[1].decode('utf8') in ["wrongUserName","serverSaturated","userExists"]: self.clientProxy.connectionRejectedONE(packet.data[1].decode("utf8")) elif 'wrongNumSeq:' in packet.data[1].decode("utf8"): self.num_seq=int(packet.data[1][12:].decode("utf8")) print("error :",packet.data[1].decode("utf8")) return 0
def connectionMovieRoom(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) # the joined room if self.existMovie(packet.data[1].decode("utf-8")) == False: self.error('Movie Room Does Not Exist') print(packet.data[1].decode("utf-8"), 'Movie Room Does Not Exist', self.serverProxy.getMovieList()) else: print('the room does exist ') self.movieRoom = (packet.data[1].decode("utf-8")) # mettre à jour la liste des utilisateur du movie room dans le serveur self.serverProxy.updateUserChatroom(self.user_name, self.movieRoom) # self.serverProxy.startStreamingMovie(self.movieRoom) self.updateUserList(movie_room=self.movieRoom)
class c2wTcpChatClientProtocol(Protocol): def __init__(self, clientProxy, serverAddress, serverPort): """ :param clientProxy: The clientProxy, which the protocol must use to interact with the Graphical User Interface. :param serverAddress: The IP address (or the name) of the c2w server, given by the user. :param serverPort: The port number used by the c2w server, given by the user. Class implementing the UDP version of the client protocol. .. note:: You must write the implementation of this class. Each instance must have at least the following attribute: .. attribute:: clientProxy The clientProxy, which the protocol must use to interact with the Graphical User Interface. .. attribute:: serverAddress The IP address of the c2w server. .. attribute:: serverPort The port number used by the c2w server. .. note:: You must add attributes and methods to this class in order to have a working and complete implementation of the c2w protocol. """ #: The IP address of the c2w server. self.serverAddress = serverAddress #: The port number used by the c2w server. self.serverPort = serverPort #: The clientProxy, which the protocol must use #: to interact with the Graphical User Interface. self.clientProxy = clientProxy self.movie_list = [] self.user_list = [] self.num_seq = 0 self.expected_num_seq = 0 self.user_name = "" self.timer = None self.room = '' self.booleanDict = {} #dictionnaire de boolean self.received_packet_history = {} self.sent_packet_history = {} self.buf = b'' self.packet = Packet(-1, 0, 0, []) self.datagram = b'' self.buf_total = b'' self.sendAndWait = True self.queuePacket = [] def sendLoginRequestOIE(self, userName): """ :param string userName: The user name that the user has typed. The client proxy calls this function when the user clicks on the login button. """ moduleLogger.debug('loginRequest called with username=%s', userName) packet = Packet(0, 0, len(userName) + 1, [len(userName), userName]) self.sendPacket(packet) # dés que j'envoie un data j'incremente mon num seq self.user_name = userName def sendChatMessageOIE(self, message): """ :param message: The text of the chat message. :type message: string Called by the client proxy when the user has decided to send a chat message .. note:: This is the only function handling chat messages, irrespective of the room where the user is. Therefore it is up to the c2wChatClientProctocol or to the server to make sure that this message is handled properly, i.e., it is shown only by the client(s) who are in the same room. """ message = ''.join(filter(lambda x: x in printable, message)) seqNumber = self.num_seq message_packet = Packet(64, seqNumber, len(self.user_name) + len(message) + 2, [ len(self.user_name), self.user_name.encode('utf-8'), len(message), message.encode('utf8') ]) message_packet.packet_format = '!LB' + str( message_packet.data[0]) + 's' + 'B' + str( message_packet.data[2]) + 's' self.sendPacket(message_packet) def ack(self, packet, host_port): ack = Packet(80, packet.numSeq, 0, None) self.transport.write(ack.pack(), host_port) def sendJoinRoomRequestOIE(self, roomName): """ :param roomName: The room name (or movie title.) Called by the client proxy when the user has clicked on the watch button or the leave button, indicating that she/he wants to change room. .. warning: The controller sets roomName to c2w.main.constants.ROOM_IDS.MAIN_ROOM when the user wants to go back to the main room. """ self.asked_room = roomName # disconnection from a movie room to the main room if roomName == ROOM_IDS.MAIN_ROOM: main_packet = Packet(49, self.num_seq, 0, None) self.sendPacket(main_packet) # connection to a movie room: else: movie_packet = Packet(48, self.num_seq, len(roomName) + 1, [len(roomName), roomName]) self.sendPacket(movie_packet) def sendLeaveSystemRequestOIE(self): """ Called by the client proxy when the user has clicked on the leave button in the main room. """ leave_paquet = Packet(3, self.num_seq, 0, "") self.sendPacket(leave_paquet) def dataReceived(self, data): """ :param string buf: the payload of the UDP packet. :param host_port: a touple containing the source IP address and port. Called **by Twisted** when the client has received a UDP packet. """ time1 = time.time() self.buf_total += data self.buf += data # print("buf tota",self.buf_total) while (True): #print("packet length", self.packet.packet_length, "len buf", len(self.buf)) if self.packet.message_type == -1 and len(self.buf) >= 4: self.packet.unpackHeader(self.buf[:4]) print("while packet", self.packet.packet_length) print("while self buf", self.buf[:4]) self.datagram = self.buf[:4] self.buf = self.buf[4:] elif self.packet.message_type != -1 and self.packet.packet_length <= len( self.buf): self.datagram += self.buf[:self.packet.packet_length] self.buf = self.buf[self.packet.packet_length:] self.datagram_treatment((self.packet, self.datagram)) self.packet = Packet(-1, 0, 0, []) else: break print(time.time() - time1, "sec") def datagram_treatment(self, packbuf): print("CLIENT RECEIVED PACKET", packbuf[0]) packet = packbuf[0] buf = packbuf[1] # if we receive a message we ack it if packet.message_type != 80: self.ack(packet) # here we have a verified num_seq and and ack message we should cancel our callater if (packet.message_type == 80): print('Ack received') if self.num_seq == packet.num_seq: self.num_seq = (self.num_seq + 1) % 2047 if self.timer is not None: self.timer.cancel() self.timer = None self.sendAndWait = True self.sendQueue() if self.lastPacketSent().message_type in [48, 49]: # if we receive the ack of join room or leave room self.room = self.asked_room self.clientProxy.joinRoomOKONE() pass elif self.lastPacketSent().message_type == 3: # if we receive the ack of leave main room self.clientProxy.leaveSystemOKONE() else: print("acquittement non pris en comtpe", packet) elif packet.num_seq in self.received_packet_history.keys( ) and self.received_packet_history[packet.num_seq].isEqual(packet): print("paquet ignoré", packet, self.received_packet_history[packet.num_seq]) elif self.expected_num_seq != packet.num_seq and packet.num_seq in self.received_packet_history.keys( ) and not self.received_packet_history[packet.num_seq].isEqual(packet): # todo self.wrongExpectedNumSeq() error = "error " + str(self.expected_num_seq) + " ! = " + str( packet.num_seq) print(error) # dans ce stade on est sur que le num seq est verifié et quil sagit pas dun message d'ack elif self.sendAndWait: print('') self.received_packet_history[packet.num_seq] = packet self.expected_num_seq += 1 if packet.message_type == 1: print('connexion etablie') elif packet.message_type == 2: print('connexion echouée') elif packet.message_type == 128: self.errorReceived(buf) elif packet.message_type == 16: self.movieListReceived(packet, buf) elif packet.message_type == 19: self.updateUserListMainRoom(packet, buf) elif packet.message_type == 65: self.chatReceived(packet, buf) elif packet.message_type == 18: self.updateUserListMovieRoom(packet, buf) else: pass def chatReceived(self, packet, buf): packet.data = [0, 0, 0, 0] # offset=4 # lenSender=struct.unpack_from('!B',buf,offset)[0] # offset+=1 # sender=struct.unpack_from('!'+str(lenSender)+'s',offset)[0] # offset+=lenSender # lenMessage=struct.unpack_from('!B',buf,offset)[0] # message=struct.unpack_from('!'+str(lenMessage)+'s') len_sender = struct.unpack_from('!B', buf, offset=4)[0] format = '!LB' + str(len_sender) + 'sB' + str(packet.packet_length - 2 - len_sender) + 's' headerDec, packet.data[0], packet.data[1], packet.data[2], packet.data[ 3] = struct.unpack(format, buf) if packet.data[1].decode('utf-8') != self.user_name: self.clientProxy.chatMessageReceivedONE( packet.data[1].decode('utf8'), packet.data[3].decode('utf8')) def wrongExpectedNumSeq(self): self.error('wrongNumSeq:' + str(self.expected_num_seq)) def error(self, errorType): error = Packet(128, self.num_seq, len(errorType) + 1, [len(errorType), errorType]) self.sendPacket(error) def errorReceived(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) print("ERREUR", packet.data[1].decode("utf8")) if packet.data[1].decode('utf8') in [ "wrongUserName", "serverSaturated", "userExists" ]: self.clientProxy.connectionRejectedONE( packet.data[1].decode("utf8")) elif 'wrongNumSeq:' in packet.data[1].decode("utf8"): self.num_seq = int(packet.data[1][12:].decode("utf8")) print("new num seq", self.num_seq) pass print("error :", packet.data[1].decode("utf8")) return 0 def updateUserListMainRoom(self, packet, buf): # here we receive the new list of user in main room self.user_list = [] packet.data = [] offset = 4 len_Rooms = struct.unpack_from("!H", buf, offset)[0] # number of movie room i = 0 offset += 2 packet.data.append(len_Rooms) for i in range(len_Rooms): len_UserList = struct.unpack_from('!H', buf, offset=offset)[0] packet.data.append(len_UserList) offset += 2 if len_UserList != 0: # if room is not empty for j in range(0, len_UserList): len_UserName = struct.unpack_from('!B', buf, offset=offset)[0] packet.data.append(len_UserName) offset += 1 user = struct.unpack_from("!" + str(len_UserName) + "s", buf, offset=offset)[0] packet.data.append(user.decode('utf8')) offset += len_UserName if i == 0: movie_title = ROOM_IDS.MAIN_ROOM elif self.movie_list == []: movie_title = i else: movie_title = self.movie_list[i - 1] user_tuple = (user.decode('utf8'), movie_title ) # ("alice","batman") self.user_list.append(user_tuple) if "initok" in self.booleanDict and self.booleanDict["initok"] == True: print("set user ok") self.clientProxy.setUserListONE(self.user_list) else: pass def updateUserListMovieRoom(self, packet, buf): self.user_list = [] packet.data = [] offset = 4 len_users = struct.unpack_from("!H", buf, offset)[0] # nombre de users offset += 2 packet.data.append(len_users) for j in range(0, len_users): len_UserName = struct.unpack_from('!B', buf, offset=offset)[0] packet.data.append(len_UserName) offset += 1 user = struct.unpack_from("!" + str(len_UserName) + "s", buf, offset=offset)[0] packet.data.append(user.decode('utf8')) offset += len_UserName user_tuple = (user.decode('utf8'), self.room) self.user_list.append(user_tuple) self.clientProxy.setUserListONE(self.user_list) def movieListReceived(self, packet, buf): self.movie_list = [] packet.data = [] len_movie_list = struct.unpack_from("!H", buf, offset=4)[0] # nombre de salon packet.data.append(len_movie_list) offset = 6 i = 0 while i < len_movie_list: format = "!B" len_movie_title = struct.unpack_from(format, buf, offset=offset)[0] packet.data.append(len_movie_title) format = "!" + str(len_movie_title) + "s" offset += 1 movie_title = struct.unpack_from(format, buf, offset=offset)[0] packet.data.append(movie_title.decode("utf8")) ip_movie = [] format = "!B" offset += len_movie_title # unpacker l'adresse ip for j in range(0, 4): ip_movie.append( struct.unpack_from(format, buf, offset=offset)[0]) offset += 1 ip_movie = list(map( str, ip_movie)) # ecrire dans une liste les 4 octet de l'adresse ip packet.data.append('.'.join(list(map(str, ip_movie)))) format = '!H' port_movie = struct.unpack_from(format, buf, offset)[0] packet.data.append(port_movie) offset += 2 i = i + 1 movie_tuple = (movie_title.decode("utf8"), ip_movie, port_movie) self.movie_list.append(movie_tuple) user_list_update = [] for user in self.user_list: if user[1] != ROOM_IDS.MAIN_ROOM: movie_title = self.movie_list[user[1] - 1] else: movie_title = ROOM_IDS.MAIN_ROOM user_list_update.append((user[0], movie_title)) self.user_list = user_list_update self.clientProxy.initCompleteONE(self.user_list, self.movie_list) self.booleanDict['initok'] = True def sendPacket(self, packet, call_count=1): if self.sendAndWait and call_count == 1: print('CLIENT ' + self.user_name + ' SEND PACKET', packet) self.transport.write(packet.pack()) self.sendAndWait = False self.sent_packet_history[packet.num_seq] = packet call_count += 1 if call_count <= 4: self.timer = reactor.callLater(5, self.sendPacket, packet, call_count) elif call_count > 1: print('CLIENT ' + self.user_name + ' SEND PACKET', packet) self.transport.write(packet.pack()) call_count += 1 if call_count <= 4: self.timer = reactor.callLater(5, self.sendPacket, packet, call_count) else: self.queuePacket.append(packet) print("packet ajoute a la queupacket", packet) def sendQueue(self): for packet in self.queuePacket: self.sendPacket(packet) self.queuePacket = [] def ack(self, packet): ack = Packet(80, packet.num_seq, 0, None) self.transport.write(ack.pack()) print("ack de", packet) def lastPacketReceived(self): return self.received_packet_history[ len(self.received_packet_history.keys()) - 1] def nlastPacketReceived(self, i): return self.received_packet_history[ len(self.received_packet_history.keys()) - i] def lastPacketSent(self): return self.sent_packet_history[len(self.sent_packet_history.keys()) - 1] def nlastPacketSent(self, i): return self.sent_packet_history[len(self.sent_packet_history.keys()) - i]
def datagramReceived(self, datagram, host_port): """ :param string datagram: the payload of the UDP packet. :param host_port: a touple containing the source IP address and port. Called **by Twisted** when the client has received a UDP packet. """ packet = Packet(0, 0, 0, 0) packet.unpackHeader(datagram) print("CLIENT RECEIVE A PACKET",packet) #if we receive a message we ack it if packet.message_type != 80 : self.ack(packet,host_port) #here we have a verified num_seq and and ack message we should cancel our callater if (packet.message_type ==80): if self.num_seq==packet.num_seq: self.num_seq = (self.num_seq + 1) % 1023 if self.timer is not None: print("TIMER CANCEL") self.timer.cancel() self.timer=None self.sendAndWait = True self.sendqueuepacket() if self.lastPacketSent().message_type in [48,49]: #if we receive the ack of join room or leave room self.room=self.room_wanted self.clientProxy.joinRoomOKONE() elif self.lastPacketSent().message_type==3: #if we receive the ack of leave main room self.clientProxy.leaveSystemOKONE() else: return 0 elif packet.num_seq in self.received_packet_history.keys() and self.received_packet_history[packet.num_seq].isEqual(packet): print("paquet ignoré",packet,self.received_packet_history[packet.num_seq]) elif self.expected_num_seq != packet.num_seq: #todo self.wrongExpectedNumSeq(host_port) #dans ce stade on est sur que le num seq est verifié et quil sagit pas dun message d'ack elif self.sendAndWait: print('') self.received_packet_history[packet.num_seq] = packet self.expected_num_seq = (self.expected_num_seq+1)%1023 if packet.message_type ==1: print('connexion etablie') elif packet.message_type ==2: print('connexion echouée') elif packet.message_type==128: self.errorReceived(datagram) elif packet.message_type==16: self.movieListReceived(packet,datagram) elif packet.message_type==19: self.updateUserListMainRoom(packet,datagram) elif packet.message_type ==65: self.chatReceived(packet,datagram) elif packet.message_type ==18: self.updateUserListMovieRoom(packet,datagram)
class c2wTcpChatServerProtocol(Protocol): def __init__(self, serverProxy, clientAddress, clientPort): """ :param serverProxy: The serverProxy, which the protocol must use to interact with the user and movie store (i.e., the list of users and movies) in the server. :param clientAddress: The IP address (or the name) of the c2w server, given by the user. :param clientPort: The port number used by the c2w server, given by the user. Class implementing the TCP version of the client protocol. .. note:: You must write the implementation of this class. Each instance must have at least the following attribute: .. attribute:: serverProxy The serverProxy, which the protocol must use to interact with the user and movie store in the server. .. attribute:: clientAddress The IP address of the client corresponding to this protocol instance. .. attribute:: clientPort The port number used by the client corresponding to this protocol instance. .. note:: You must add attributes and methods to this class in order to have a working and complete implementation of the c2w protocol. .. note:: The IP address and port number of the client are provided only for the sake of completeness, you do not need to use them, as a TCP connection is already associated with only one client. """ #: The IP address of the client corresponding to this #: protocol instance. self.clientAddress = clientAddress #: The port number used by the client corresponding to this #: protocol instance. self.clientPort = clientPort #: The serverProxy, which the protocol must use #: to interact with the user and movie store in the server. self.serverProxy = serverProxy self.client_host_port = (self.clientAddress, self.clientPort) self.sent_packet_history = {} self.received_packet_history = {} self.errorVar = "" self.user_name = None for movie in self.serverProxy.getMovieList(): self.serverProxy.startStreamingMovie(movie.movieTitle) self.buf = b'' self.packet = Packet(-1, 0, 0, []) self.datagram = b'' self.buf_total = b'' self.sendAndWait = True self.queuePacket = [] def dataReceived(self, data): """ :param data: The data received from the client (not necessarily an entire message!) Twisted calls this method whenever new data is received on this connection. """ # self.buf_total+=data self.buf += data # print("buf tota",self.buf_total) while (True): #print("packet length", self.packet.packet_length, "len buf", len(self.buf)) if self.packet.message_type == -1 and len(self.buf) >= 4: self.packet.unpackHeader(self.buf[:4]) #print("while packet", self.packet.packet_length) #print("while self buf", self.buf[:4]) self.datagram = self.buf[:4] self.buf = self.buf[4:] elif self.packet.message_type != -1 and self.packet.packet_length <= len( self.buf): self.datagram += self.buf[:self.packet.packet_length] self.buf = self.buf[self.packet.packet_length:] self.datagram_treatment((self.packet, self.datagram)) self.packet = Packet(-1, 0, 0, []) elif self.packet.packet_length > 100: self.buf = b'' self.packet = Packet(-1, 0, 0, []) self.datagram = b'' else: break def datagram_treatment(self, packbuf): packet = packbuf[0] buf = packbuf[1] user_name_print = "unknown" if self.user_name is not None: user_name_print = self.user_name print("SERVER RECEIVED PACKET" + user_name_print, packet) # if the buf received is not an ack then we send an ack if packet.message_type != 80: self.ack(packet) print('Ack sent') if packet.message_type == 0: self.connectionResponse(buf) # if it's and ack of connecion done we send user list then movielist elif (packet.message_type == 80): if packet.num_seq == self.num_seq: if self.num_seq == packet.num_seq: self.num_seq = (self.num_seq + 1) % 2047 if self.timer is not None: print("TIMER CANCEL") self.timer.cancel() self.timer = None self.sendAndWait = True self.sendQueue() if self.lastPacketSent().message_type == 1: self.updateUserList(ROOM_IDS.MAIN_ROOM) elif self.nlastPacketSent(2).message_type == 1: self.sendMovieList() elif self.lastPacketSent().message_type == 2: self.error(self.errorVar) else: return 0 # old ack elif packet.num_seq in self.received_packet_history.keys( ) and self.received_packet_history[packet.num_seq].isEqual(packet): print("paquet ignoré", packet, self.received_packet_history[packet.num_seq]) elif self.expected_num_seq != packet.num_seq: self.wrongExpectedNumSeq() error = "error " + str(self.expected_num_seq) + " ! = " + str( packet.num_seq) print(error) # if it's and ack of connecion done we send movie list then userlist # here we are sure that the num sq is verified and that i's not an ack elif self.sendAndWait: self.received_packet_history[packet.num_seq] = packet self.expected_num_seq += 1 if packet.message_type == 64: print("MESSAGE BIEN RECU") self.forward(packet, buf) elif packet.message_type == 48: self.connectionMovieRoom(buf) elif packet.message_type == 49: print("PAQUET DECONNEXION RECU") self.deconnectionMovieRoom() elif packet.message_type == 3: self.leaveSystem() elif packet.message_type == 128: self.errorReceived(buf) else: pass def forward(self, packet, buf): len_sender = struct.unpack_from('!B', buf, offset=4)[0] format = '!LB' + str(len_sender) + 'sB' + str(packet.packet_length - 2 - len_sender) + 's' packet.data = [0, 0, 0, 0] headerDec, packet.data[0], packet.data[1], packet.data[2], packet.data[ 3] = struct.unpack(format, buf) if self.malformed(packet.data[3].decode('utf8')): self.error("malformed message") else: user_chat_room_dict = self.getUserChatRoomDict() if self.movieRoom == ROOM_IDS.MAIN_ROOM: sender_chat_room = "main_room" else: sender_chat_room = self.movieRoom i = 0 while i < len(user_chat_room_dict[sender_chat_room]): receiver = user_chat_room_dict[sender_chat_room][i] print("FORWARD5") messagePacket = Packet(65, -1, packet.packet_length, packet.data, format) self.serverProxy.getUserByName( receiver).userChatInstance.sendPacket(messagePacket) print("FORWARD6") i += 1 def connectionMovieRoom(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) # the joined room if self.existMovie(packet.data[1].decode("utf-8")) == False: self.error('Movie Room Does Not Exist') print(packet.data[1].decode("utf-8"), 'Movie Room Does Not Exist', self.serverProxy.getMovieList()) else: print('the room does exist ') self.movieRoom = (packet.data[1].decode("utf-8")) # mettre à jour la liste des utilisateur du movie room dans le serveur self.serverProxy.updateUserChatroom(self.user_name, self.movieRoom) # self.serverProxy.startStreamingMovie(self.movieRoom) self.updateUserList(movie_room=self.movieRoom) def existMovie(self, movieRoom): Exist = False for movie in self.serverProxy.getMovieList(): if movieRoom == movie.movieTitle: Exist = True return (Exist) def leaveSystem(self): old_movie_room = self.movieRoom self.serverProxy.removeUser(self.user_name) self.updateUserList(movie_room=old_movie_room) def deconnectionMovieRoom(self): old_movie_room = self.movieRoom self.movieRoom = ROOM_IDS.MAIN_ROOM self.serverProxy.updateUserChatroom(self.user_name, self.movieRoom) self.updateUserList(movie_room=old_movie_room) print("DECONNECTION OK") def connectionResponse(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) userName = packet.data[1].decode("utf-8") self.user_name = userName if self.serverProxy.userExists(userName): # num seq a traiter #todo self.expected_num_seq = 1 self.num_seq = 0 self.sent_packet_history = {} self.received_packet_history = {} self.failed() self.errorVar = "userExists" elif self.malformed(userName, user_name=True) == True: self.expected_num_seq = 1 self.num_seq = 0 self.sent_packet_history = {} self.received_packet_history = {} self.failed() self.errorVar = "malformed User Name" elif len(self.serverProxy.getUserList()) >= 513: self.expected_num_seq = 1 self.num_seq = 0 self.sent_packet_history = {} self.received_packet_history = {} self.failed() self.errorVar = "serverSaturated" else: self.expected_num_seq = 1 self.num_seq = 0 self.sent_packet_history = {} self.received_packet_history = {} self.serverProxy.addUser(userName, ROOM_IDS.MAIN_ROOM, self, self.client_host_port) self.movieRoom = ROOM_IDS.MAIN_ROOM connectionDone = Packet(1, self.num_seq, 0, '') self.sendPacket(connectionDone) # ????? self.serverProxy.updateUserChatroom(userName, ROOM_IDS.MAIN_ROOM) def malformed(self, message, user_name=False): if not user_name: message = message[:-1] return False elif len(message) == 0 or ( len(message) <= 255 and message[0].isalpha() and (len(message) == 1 or message[1:].isalnum())): return False return True def ack(self, packet): ack = Packet(80, packet.num_seq, 0, None) self.transport.write(ack.pack()) user_name = 'unknown' if self.user_name is not None: user_name = self.user_name print('ACK', packet.num_seq, user_name) def error(self, errorType): error = Packet(128, self.num_seq, len(errorType) + 1, [len(errorType), errorType]) self.sendPacket(error) def errorReceived(self, buf): packet = Packet(0, 0, 0, 0) packet.unpackHeader(buf) format = '!LB' + str(packet.packet_length - 1) + 's' packet.data = [0, 0] headerDec, packet.data[0], packet.data[1] = struct.unpack(format, buf) print("ERREUR", packet.data[1].decode("utf8")) if 'wrongNumSeq:' in packet.data[1].decode('utf8'): self.num_seq = int(packet.data[1][12:].decode("utf8")) print("new num seq", self.num_seq) print("error :", packet.data[1].decode("utf8")) return 0 def wrongExpectedNumSeq(self): self.error('wrongNumSeq:' + str(self.expected_num_seq)) def failed(self): failed = Packet(2, self.num_seq, 0, '') self.sendPacket(failed) def sendMovieList(self): # we send list of movie sorted movie_list = self.serverProxy.getMovieList() movie_list = sorted(movie_list, key=lambda x: x.movieTitle) data = [] length = 2 format = "!LH" data.append(len(movie_list)) for movie in movie_list: format += "B" + str(len(movie.movieTitle)) + "sBBBBH" data.append(len(movie.movieTitle)) data.append(movie.movieTitle.encode("utf-8")) print('movie.movieIpAddress', movie.movieIpAddress) data = data + list(map(int, movie.movieIpAddress.split("."))) data.append(movie.moviePort) # 1 byte -> lenghtmovie title, 4 bytes -> length ipv4 , 2 bytes -> port length = length + 1 + len(movie.movieTitle) + 4 + 2 movie_list_packet = Packet(16, self.num_seq, length, data, format) self.sendPacket(movie_list_packet) def updateUserList(self, movie_room): # if user joined a main room: WE SEND TO EACH USER IN MAIN ROOM (EVEN THE USER HIMSELF) "UserListMainRoom" # if user joined a movie room: WE SEND TO EACH USER IN THAT MOVIE ROOM "UserListMovieRoom": # # WE SEND TO EACH USER IN THE MAIN ROOM "UserListMainRoom" user_list = self.serverProxy.getUserList( ) # list of all users connected to the server # update user list in the case of joining the system if movie_room == ROOM_IDS.MAIN_ROOM: # I look for users in that main room and I send them the appropriate list for user in user_list: if user.userChatRoom == ROOM_IDS.MAIN_ROOM: user.userChatInstance.sendUserListMainRoom() # update user list else: for user in user_list: if user.userChatRoom == movie_room: user.userChatInstance.sendUserListMovieRoom( user.userChatRoom) elif user.userChatRoom == ROOM_IDS.MAIN_ROOM: user.userChatInstance.sendUserListMainRoom() def sendUserListMovieRoom(self, movie_room): # send the Packet of usersList in a movie room to the user user_chat_room_dict = self.getUserChatRoomDict() update_user_list_packet = Packet(18, -1, 0, []) update_user_list_packet.data.append( len(user_chat_room_dict[movie_room])) update_user_list_packet.packet_format = "!LH" update_user_list_packet.packet_length = 2 for user_chat_room in user_chat_room_dict[movie_room]: update_user_list_packet.packet_format += "B" + str( len(user_chat_room)) + "s" update_user_list_packet.packet_length += 1 + len(user_chat_room) update_user_list_packet.data.append(len(user_chat_room)) update_user_list_packet.data.append(user_chat_room.encode("utf8")) print("user list movie", update_user_list_packet) self.sendPacket(update_user_list_packet) def sendUserListMainRoom(self): user_list_packet = Packet(19, -1, 2, [], "!LH") user_chat_room_dict = {} user_chat_room_dict["main_room"] = [] for movie in self.serverProxy.getMovieList(): user_chat_room_dict[movie.movieTitle] = [] # user_chat_room_dict={"main_room":[5,alice,3,bob];"batmann":[5,mario]... user_list = self.serverProxy.getUserList() for user in user_list: if user.userChatRoom == ROOM_IDS.MAIN_ROOM: user_chat_room_dict["main_room"].append(len(user.userName)) user_chat_room_dict["main_room"].append( user.userName.encode('utf8')) else: user_chat_room_dict[user.userChatRoom].append( len(user.userName)) user_chat_room_dict[user.userChatRoom].append( user.userName.encode('utf8')) user_list_packet.packet_length += 1 + len(user.userName) data = [] # data= [Nombre de room,NombreUtilisateurMainRoom,5,alice,3,bob] user_list_packet.packet_format += "H" data.append(len(user_chat_room_dict.keys())) data.append(int(len(user_chat_room_dict["main_room"]) / 2)) data += user_chat_room_dict["main_room"] user_list_packet.packet_length += 2 i = 0 while i < len(user_chat_room_dict["main_room"]): user_list_packet.packet_format += "B" + str( user_chat_room_dict["main_room"][i]) + "s" i += 2 del user_chat_room_dict["main_room"] for movie in sorted(user_chat_room_dict.keys()): user_list_packet.packet_length += 2 user_list_packet.packet_format += "H" data.append(int(len(user_chat_room_dict[movie]) / 2)) data += user_chat_room_dict[movie] i = 0 while i < len(user_chat_room_dict[movie]): user_list_packet.packet_format += "B" + str( user_chat_room_dict[movie][i]) + "s" i += 2 user_list_packet.data = data self.sendPacket(user_list_packet) def sendPacket(self, packet, call_count=1): if self.sendAndWait and call_count == 1: if (packet.message_type in [65, 18, 19]): packet.num_seq = self.num_seq self.sendAndWait = False print('SERVER SEND PACKET TO ' + self.user_name, packet) self.transport.write(packet.pack()) self.sent_packet_history[packet.num_seq] = packet print("callcount", call_count) call_count += 1 if call_count <= 4: self.timer = reactor.callLater(5, self.sendPacket, packet, call_count) elif call_count > 1: print('SERVER SEND PACKET TO ' + self.user_name, packet) self.transport.write(packet.pack()) call_count += 1 if call_count <= 4: self.timer = reactor.callLater(5, self.sendPacket, packet, call_count) else: self.queuePacket.append(packet) print("packet stocke", packet) def sendQueue(self): for packet in self.queuePacket: self.sendPacket(packet) self.queuePacket = [] # UTILS def lastPacketReceived(self): return self.received_packet_history[ len(self.received_packet_history.keys()) - 1] def nlastPacketReceived(self, i): return self.received_packet_history[ len(self.received_packet_history.keys()) - i] def lastPacketSent(self): return self.sent_packet_history[len(self.sent_packet_history.keys()) - 1] def nlastPacketSent(self, i): if len(self.sent_packet_history) > ( len(self.sent_packet_history.keys()) - i) and (len(self.sent_packet_history.keys()) - i) >= 0: return self.sent_packet_history[ len(self.sent_packet_history.keys()) - i] else: return Packet(None, None, None, None) def getUserChatRoomDict(self): """ this method return a dict with dict[movie_room]= [list of user of the movie room] :return: """ user_chat_room_dict = {} user_chat_room_dict["main_room"] = [] for movie in self.serverProxy.getMovieList(): user_chat_room_dict[movie.movieTitle] = [] user_list = self.serverProxy.getUserList() for user in user_list: if user.userChatRoom == ROOM_IDS.MAIN_ROOM: user_chat_room_dict["main_room"].append(user.userName) else: user_chat_room_dict[user.userChatRoom].append(user.userName) return user_chat_room_dict
def datagramReceived(self, datagram, host_port): """ :param string datagram: the payload of the UDP packet. :param host_port: a touple containing the source IP address and port. Twisted calls this method when the server has received a UDP packet. You cannot change the signature of this method. """ packet = Packet(0, 0, 0, 0) packet.unpackHeader(datagram) print("SERVER RECEIVING PACKET", packet) if self.serverProxy.getUserByAddress(host_port) is not None: user_name = self.serverProxy.getUserByAddress(host_port).userName elif host_port in self.num_seq.keys(): user_name = host_port else: user_name = None print('host_port', host_port) #if the datagram received is not an ack then we send an ack if packet.message_type != 80: self.ack(packet, host_port) if packet.message_type == 0: self.connectionResponse(datagram, packet, host_port) #if it's and ack of connecion done we send user list then movielist elif (packet.message_type == 80): if packet.num_seq == self.num_seq[user_name]: self.num_seq[user_name] = (self.num_seq[user_name] + 1) % 1023 if self.timer[user_name] != None: self.timer[user_name].cancel() self.timer[user_name] = None self.sendAndWait = True self.sendqueuepacket() if self.lastPacketSent(user_name).message_type == 1: self.updateUserList(ROOM_IDS.MAIN_ROOM) elif self.nlastPacketSent(user_name, 2).message_type == 1: self.sendMovieList(user_name, host_port) elif self.lastPacketSent(user_name).message_type == 2: self.error(self.errorDict[user_name], host_port, user_name) else: return 0 #old ack elif packet.num_seq in self.received_packet_history.keys( ) and self.received_packet_history[packet.num_seq].isEqual(packet): print("paquet ignoré", packet, self.received_packet_history[packet.num_seq]) elif self.expected_num_seq[user_name] != packet.num_seq: self.wrongExpectedNumSeq(host_port, user_name) print("ERROR") #if it's and ack of connecion done we send movie list then userlist #here we are sure that the num sq is verified and that i's not an ack else: self.received_packet_history[user_name][packet.num_seq] = packet self.expected_num_seq[user_name] = ( self.expected_num_seq[user_name] + 1) % 1023 if packet.message_type == 64: print("MESSAGE BIEN RECU") self.forward(packet, datagram, host_port, user_name) elif packet.message_type == 48: self.connectionMovieRoom(datagram, packet, host_port, user_name) elif packet.message_type == 49: self.deconnectionMovieRoom(datagram, packet, host_port, user_name) elif packet.message_type == 3: self.leaveSystem(user_name) elif packet.message == 128: self.errorReceived(datagram, user_name)