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 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 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 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 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 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 sendUserListMainRoom(self, user_name, host_port): user_list_packet = Packet(19, self.num_seq[user_name], 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, host_port)
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 nlastPacketSent(self, user_name, i): if len(self.sent_packet_history[user_name]) > ( len(self.sent_packet_history[user_name].keys()) - i) and ( len(self.sent_packet_history[user_name].keys()) - i) >= 0: return self.sent_packet_history[user_name][ len(self.sent_packet_history[user_name].keys()) - i] else: return Packet(None, None, None, None)
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 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, 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 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 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 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 sendUserListMovieRoom(self, user, 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, self.num_seq[user.userName], 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")) self.sendPacket(update_user_list_packet, user.userAddress)
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 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 forward(self, packet, datagram, host_port, user_name): len_sender = struct.unpack_from('!B', datagram, 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, datagram) if self.malformed(packet.data[3].decode('utf8')): self.error("malformed message", host_port, user_name=user_name) else: user_chat_room_dict = self.getUserChatRoomDict() if self.movieRoom[packet.data[1].decode( 'utf8')] == ROOM_IDS.MAIN_ROOM: sender_chat_room = "main_room" else: sender_chat_room = self.movieRoom[packet.data[1].decode( 'utf8')] 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, self.num_seq[receiver], packet.packet_length, packet.data, format) #messagePacket.packet_format="!LB" + str(self.data[0]) + 's' + "B" + str(self.data[2]) + 's' self.sendPacket( messagePacket, self.serverProxy.getUserByName(receiver).userAddress) print("FORWARD6") i += 1
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 failed(self, host_port): failed = Packet(2, self.num_seq[host_port], 0, '') self.sendPacket(failed, host_port)
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)
def ack(self, packet): ack = Packet(80, packet.num_seq, 0, None) self.transport.write(ack.pack()) print("ack de", packet)
def error(self, errorType): error = Packet(128, self.num_seq, len(errorType) + 1, [len(errorType), errorType]) self.sendPacket(error)
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 __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 error(self, errorType, host_port, user_name): error = Packet(128, self.num_seq[user_name], len(errorType) + 1, [len(errorType), errorType]) self.sendPacket(error, host_port)
def ack(self, packet, host_port): ack = Packet(80, packet.numSeq, 0, None) self.transport.write(ack.pack(), host_port)
def failed(self): failed = Packet(2, self.num_seq, 0, '') self.sendPacket(failed)
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)