def recibirVideoBuffer(self, vc): """ Función que recibe video y lo almacena en el buffer Args: self -> la misma clase vc -> interfaz gráfica de la aplicación """ while 1: #Recibe datos. Si pasa el timeout sin estar en llamada, sale del hilo. Sino, mensaje de error y sale try: data, addr = self.sock_rcv.recvfrom(65535) except socket.timeout as e: if self.llamada == False: break else: vc.app.warningBox("Timeout", "Conexion perdida") res = p.info_decode(vc.UDPcon.dest) t.enviarTCP("CALL_END " + vc.user, False, res[0], int(res[1])) vc.app.hideButton("Colgar") vc.app.hideButton("Pausa") vc.app.hideSubWindow("El otro") vc.UDPcon = None #Si ha recibido datos, decodifica la cabecera y parsea la imagen if data: request = data.split(b"#") indice = request[0] ts = request[1] res = request[2] fps = request[3] imagen = b'#'.join(request[4:]) imagen = numpy.fromstring(imagen, dtype='uint8') imagen = cv2.imdecode(imagen, 1) cv2_im = cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB) img_tk = ImageTk.PhotoImage(Image.fromarray(cv2_im)) #Genera un diccionario y lo mete en el buffer dict = { 'indice': indice, 'ts': ts, 'res': res, 'fps': fps, 'imagen': img_tk } self.buffer.add(dict)
def salir(): """ Función que sale del programa Args : void Returns : mensaje a imprimir para salir """ # Enviamos el mensaje y devolvemos la respuesta mensaje = "QUIT" recv = t.enviarTCP(mensaje) return recv
def llamar(nick, ip, puerto): """ Función que establece la llamada Args : nick -> nick del usuario que llama ip -> ip de usuario a llamar puerto -> puerto TCP del usuario a llamar Returns : respuesta de la conexión de control """ # Enviamos el mensaje a la conexión de control del otrp usuario recv = t.enviarTCP("CALLING " + nick + " " + str(u.UDP_PORT), False, ip, puerto) mensaje = recv.decode().split(" ") # Si acepta la llamada, devolvemos su nick y su puerto UDP if mensaje[0] == "CALL_ACCEPTED": return mensaje[1], mensaje[2] # Si deniega la llamada enviamos False y DENIED elif mensaje[0] == "CALL_DENIED": return False, "DENIED" # Si está ocupado, enviamos False y BUSY else: return False, "BUSY"
def usuarios(): """ Función que devuelve la lista de usuarios Args : void Returns : lista de usuarios a imprimir """ # Enviamos el mensaje y decodificamos la respuesta mensaje = "LIST_USERS" recv = t.enviarTCP(mensaje, True) # Si la respuesta es OK devolvemos la lista de usuarios if recv.decode()[0] == "O": # La dividimos por '#' respuesta = recv.decode().split("#") pr = respuesta[0].split(" ") res = pr[3] + " " + pr[4] + " " + pr[5] + " " + pr[6] + "\n" for i in range(1, len(respuesta) - 1): res = res + respuesta[i] + "\n" return res # Sino devolvemos un mensaje de error else: return recv.decode()
def usuarios_decode(): """ Función que devuelve la lista de usuarios por tuplas Args : void Returns : lista de usuarios a imprimir por tuplas """ # Enviamos el mensaje y decodificamos la respuesta mensaje = "LIST_USERS" recv = t.enviarTCP(mensaje, True) # Si la respuesta es OK devolvemos la lista de usuarios if recv.decode()[0] == "O": # La dividimos por '#' respuesta = recv.decode().split("#") pr = respuesta[0].split(" ") res0 = [pr[3], pr[4], pr[5]] res = [pr.split()[:3] for pr in respuesta[1:-1]] res = [res0] + res res = [["Usuario", "Dirección IP", "Puerto"]] + res return res # Sino devolvemos un mensaje de error else: return recv.decode()
def info(name): """ Función que devuelve la ip y puerto de un usuario a través de su nick Args : name -> nombre del usuario Returns : ip y puerto del usuario """ # Enviamos el mensaje y decodificamos la respuesta mensaje = "QUERY " + name recv = t.enviarTCP(mensaje) respuesta = recv.decode().split(" ") # Si la respuesta es OK devolvemos el mensaje completo if respuesta[0] == "OK": prot = respuesta[5].split("#") res = "Usuario: " + respuesta[2] + "\nDirección IP: " + respuesta[ 3] + "\nPuerto: " + respuesta[4] + "\nProtocolos: " for i in range(0, len(prot)): res = res + prot[i] + " " return res # Sino devolvemos un mensaje de error else: return recv.decode()
def registrar(nick, ip_address, port, password, protocol): """ Función que registra un usuario en el servidor Args : nick -> nombre del usuario ip_address -> dirección ip del usuario password -> contraseña del usuario protocol -> protocolo del servidor utilizado Returns : mensaje a imprimir """ # Enviamos el mensaje y decodificamos la respuesta mensaje = "REGISTER " + nick + " " + ip_address + " " + port + " " + password + " " + protocol recv = t.enviarTCP(mensaje) respuesta = recv.decode().split(" ") # Si la respuesta es OK devolvemos un mensaje completo if respuesta[0] == "OK": res = "Usuario: " + respuesta[2] + "\nts: " + respuesta[3] return res # Sino devolvemos el mensaje de error else: return recv.decode()
def buttonsCallback(self, button): """ Función que asocia acciones a los botones Args: self -> clase button -> tipo de botón que hemos pulsado """ if button == "Salir": # Salimos de la aplicación sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) PORT = int(self.puerto) sock.connect((self.ip, PORT)) sock.sendall( "Salir".encode() ) # Enviamos un mensaje a nuestra conexión de control para que salga sock.close() self.salir = True self.app.stop() elif button == "Conectar": # Entrada del nick del usuario a conectar nick = self.app.textBox("Conexión", "Introduce el nick del usuario a buscar") #Si el nick es incorrecto, pasa if not nick: pass # Sino, busca su información en el servidor else: res = p.info_decode(nick) # Si hay mensaje de error, el nick es incorrecto if res[0] == "N": self.app.warningBox("Error", "Nick incorrecto") # Sino, llama a la función de llamada con el nick propio, y la ip y el puerto del destinatario else: respuesta = p.llamar(self.user, res[0], int(res[1])) # Si se recibe un False, puede ser llamada rechazada o usuario ocupado if respuesta[0] == False: if respuesta[1] == "DENIED": self.app.warningBox( "Rechazado", "El usuario rechazó la llamada") else: self.app.warningBox("Ocupado", "El usuario está ocupado") # Sino, es llamada aceptada, se llama a la función que establece la conexión else: self.llamada(nick, res[0], respuesta[1]) # Envia a la conexión de control del destinatario el memsaje de final, y cierra la llamada elif button == "Colgar": res = p.info_decode(self.UDPcon.dest) t.enviarTCP("CALL_END " + self.user, False, res[0], int(res[1])) self.UDPcon.llamada = False time.sleep(2) self.UDPcon = None self.app.hideButton("Colgar") self.app.hideButton("Pausa") self.app.hideButton("Video") self.app.hideSubWindow("El otro") self.app.showWidgetType(3, "Conectar") # Establece el parámetro pausa a True, y envia a la conexión de control el mensaje de pausa elif button == "Pausa": self.UDPcon.pausa = True #Eliminamos el timeout para evitar problemas self.UDPcon.sock_rcv.settimeout(None) res = p.info_decode(self.UDPcon.dest) t.enviarTCP("CALL_HOLD " + self.user, False, res[0], int(res[1])) self.app.hideButton("Pausa") self.app.showWidgetType(3, "Continua") # Cambia el valor del parámetro de pausa, e informa a la conexion de control de que la llamada continúa elif button == "Continua": self.UDPcon.pausa = False #Restablece el timeout self.UDPcon.sock_rcv.settimeout(10) res = p.info_decode(self.UDPcon.dest) t.enviarTCP("CALL_RESUME " + self.user, False, res[0], int(res[1])) self.app.hideButton("Continua") self.app.showWidgetType(3, "Pausa") # Abre un cuadro de elección de ficheros en el directorio actual, y establece el video elegido como el origen de los frames elif button == "Video": filename = self.app.openBox(title="Directorio", dirName=os.getcwd(), fileTypes=[('video', '*.avi'), ('video', '*.mp4')], asFile=False, parent=None) self.cap = cv2.VideoCapture(filename)