def hold_resume(self, button): nick = self.calling_user tcp_port = int(self.usersDic[nick]['port']) ip = self.usersDic[nick]['ip'] tcp_socket = socket(AF_INET, SOCK_STREAM) tcp_socket.settimeout(5) if str(button) == self.HOLD: # Intercambiamos self.app.hideWidgetType(gui.BUTTON, self.HOLD) self.app.showWidgetType(gui.BUTTON, self.RESUME) # Congelamos self.on_hold.set() # Notificamos al otro usuario try: tcp_socket.connect((ip, tcp_port)) Protocolo.call_hold(Usuario.APP_USER.nick, tcp_socket) tcp_socket.close() except: pass if str(button) == self.RESUME: # Intercambiamos self.app.hideWidgetType(gui.BUTTON, self.RESUME) self.app.showWidgetType(gui.BUTTON, self.HOLD) # Descongelamos self.on_hold.clear() # Notificamos al otro usuario try: tcp_socket.connect((ip, tcp_port)) Protocolo.call_resume(Usuario.APP_USER.nick, tcp_socket) tcp_socket.close() except: pass return
def __hang(self, button): nick = self.calling_user self.state_lock.acquire() # Enviamos fin de conexion try: tcp_socket = socket(AF_INET, SOCK_STREAM) # Timeout para conexion con el otro usuario tcp_socket.settimeout(5) tcp_socket.connect( (self.usersDic[nick]['ip'], int(self.usersDic[nick]['port']))) Protocolo.call_end(Usuario.APP_USER.nick, tcp_socket) tcp_socket.close() except Exception as e: pass self.__change_call_buttons(self.FROM_CALL) # Finalizamos la llamada self.end_call.set() self.STATE = STATE_LOGGED self.state_lock.release() return
def control_port_listen(self): user_tcp_port = Usuario.APP_USER.tcpPort # Preparamos el socket server_socket = socket(AF_INET, SOCK_STREAM) server_socket.bind(('', int(user_tcp_port))) server_socket.listen(5) server_socket.settimeout(self.TIMEOUT) # Bucle de lectura de puerto while True: # Abrimos el mensaje/listen con timeout para probar los flags periodicamente try: conection_socket, addr = server_socket.accept() msg = conection_socket.recv(self.MAX_LISTEN) msg = msg.decode('utf-8') # Actualizamos la lista de usuarios cada vez que nos llaman self.usersDic = Protocolo.list_users() if 'CALLING' in msg: self.called_manager(msg) elif 'CALL_HOLD' in msg: self.call_hold_manager(msg) elif 'CALL_RESUME' in msg: self.call_resume_manager(msg) elif 'CALL_END' in msg: self.call_end_manager(msg) elif 'CALL_ACCEPTED' in msg: self.call_accepted_manager(msg) elif 'CALL_DENIED' in msg: self.call_denied_manager(msg) elif 'CALL_BUSY' in msg: self.call_busy_manager(msg) # Cualquier otro caso es descartado por malformacion except Exception as e: # Salimos en caso de que el hilo maestro lo indique if self.end_gui.is_set(): return
def __left_frame(self): self.app.startLabelFrame('Registered users', row=0, column=0) self.app.setSticky('we') self.app.startScrollPane(self.USERS_PANE, column=0, row=0, rowspan=2) self.usersDic = Protocolo.list_users() for user, i in zip(self.usersDic, range(len(self.usersDic))): #Aniadimos i-esimo frame self.app.startFrame(self.USER_FRAME + user, row=i, column=0, colspan=2) self.app.setSticky("nws") self.app.setExpand("both") #Metemos dentro button y label self.app.addIconButton('call.' + user, self.__call, 'md-camera-video', i, 0, 1) self.app.addLabel(user, user, i, 1, 1) self.app.stopFrame() self.app.stopScrollPane() self.app.stopLabelFrame()
def __user_register(self, usuario, clave, port, ip, udp_port): # Llamamos al protocolo para que registre/renueve el usuario result = Protocolo.register(usuario, clave, port, ip) if result: # Caso efectivo # Guardamos el nuevo diccionario con el usuario registrado self.users[usuario] = { 'port': port, 'ip': ip, 'udp_port': udp_port } with open(self.USERS, 'w') as f: json.dump(self.users, f) # Indicamos el usuario que se ha creado y cerramos el interfaz Usuario.APP_USER = Usuario(usuario, port, udp_port) self.app.stop() else: # Caso de fallo # indicamos error ind = self.app.getLabelWidget('Indicador') ind.config(text='Usuario o clave invalido.')
def __pressBusqueda(self, busquedaButton): search = self.app.getEntry(self.BUSQUEDA_ENTRY) # Borramos info antigua: frame, label y button, y el scrollPane self.app.openFrame(self.RESULTS_FRAME) try: for nick in self.searchDic: self.app.removeWidgetType(gui.BUTTON, 'callResult.' + nick) self.app.removeWidgetType(gui.FRAME, self.RESULT_FRAME + nick) self.app.removeWidgetType(gui.LABEL, 'result_' + nick) self.app.removeWidgetType('scrollPane', self.RESULTS_PANE) except Exception as e: print(e) # No usamos los users de usersDic in case hay nuevos registrados # Aprovechamos para actualizar el diccionario de todos los users self.searchDic = {} self.usersDic = Protocolo.list_users() for nick in self.usersDic: # Si la string buscada coincide con el nick, lo aniadimos al diccionario if search in nick: self.searchDic[nick] = self.usersDic[nick] # Y actualizamos el scroll pane de los resultados con los nuevos resultados self.__update_results_pane()
def called_manager(self, msg): campos = msg.split(' ') # Caso de paquete mal formado if len(campos) != 3: return nick = campos[1] dst_udp_port = campos[2] # Intentamos abrir un socket de control, sino lo logramos no hacemos nada try: tcp_socket = socket(AF_INET, SOCK_STREAM) # Timeout para conexion con el otro usuario tcp_socket.settimeout(10) tcp_socket.connect( (self.usersDic[nick]['ip'], int(self.usersDic[nick]['port']))) except Exception as e: print(e) return # Comprobamos que estamos en login, sino mandamos un paquete de ocupado self.state_lock.acquire() if self.STATE != STATE_LOGGED: # Nos protegemos contra casos de error al enviar un BUSY try: # Abrimos conexion con el puerto de control del usuario Protocolo.call_busy(Usuario.APP_USER.nick, tcp_socket) tcp_socket.close() except Exception as e: print(e) # Caso de algun fallo de ip, puerto o conexion no peta el programa self.state_lock.release() return # Creamos esta variable para comunicarnos con el subventana cuando nos llamen # Con value sabemos la decision del usuario self.value = False # Establecemos el usuario y llamamos a la ventana emergente self.calling_user_lock.acquire() self.calling_user = nick self.called_subwindow() # Esperamos a que responda el usuario self.esperar_resultado.acquire() # Caso de aceptar de llamada if self.value == True: # Abrimos un socket UDP en el que recibir el video (pedimos puerto al OS) # Lo guardamos en una variable de clase para que pueda acceder el hilo self.sock_udp = socket(AF_INET, SOCK_DGRAM) udp_port = int(Usuario.APP_USER.udp_port) self.sock_udp.bind(('', udp_port)) # Enviamos paquete de llamada aceptada Protocolo.call_accept(Usuario.APP_USER.nick, udp_port, tcp_socket) # Inciamos el thread con el inicio de la llamada t = Thread(target=self.video_managing_thread, args=(dst_udp_port, )) t.start() self.STATE = STATE_CALL self.__change_call_buttons(self.TO_CALL) else: # Caso de rechazar eliminamos el calling user self.calling_user = None Protocolo.call_deny(Usuario.APP_USER.nick, tcp_socket) tcp_socket.close() self.calling_user_lock.release() self.state_lock.release() return
def __call(self, button): # Solo podemos llamar cuando estamos en estado de logged self.state_lock.acquire() if self.STATE != STATE_LOGGED: self.state_lock.release() return self.state_lock.release() nick = button[button.find('.') + 1:] # Variable utiles del usuario a llamar tcp_port = int(self.usersDic[nick]['port']) ip = self.usersDic[nick]['ip'] self.state_lock.acquire() # Abrimos un socket UDP self.sock_udp = socket(AF_INET, SOCK_DGRAM) udp_port = int(Usuario.APP_USER.udp_port) self.sock_udp.bind(('', udp_port)) # Intentamos abrir el puerto y enviar paquete de llamada # si fallamos solo cerramos la comunicacion (posibles ips o puertos malformados) try: tcp_socket = socket(AF_INET, SOCK_STREAM) # Timeout para conectar con el otro usuario tcp_socket.settimeout(5) tcp_socket.connect((ip, tcp_port)) Protocolo.call(Usuario.APP_USER.nick, udp_port, tcp_socket) tcp_socket.close() except Exception as e: print(e) # Borramos info anterior try: self.app.destroySubWindow(self.INFO) except: pass # Indicamos que el servidor no logra conectarse self.app.startSubWindow(self.INFO, modal=True) self.app.addLabel('Indicacion2', 'El usuario esta offline') self.app.stopSubWindow() self.app.showSubWindow(self.INFO) # Cerramos self.sock_udp.close() self.state_lock.release() return # Indicamos que estamos a la espera de respuesta por parte del usuario con nick self.STATE = STATE_WAIT_ANSWER self.state_lock.release() self.calling_user_lock.acquire() self.calling_user = nick self.calling_user_lock.release() # Creamos una nueva ventana (recordar que hay que destruir la anterior) try: self.app.destroySubWindow(self.WAITING_WINDOW) except: pass self.app.startSubWindow(self.WAITING_WINDOW, modal=True) self.app.addLabel('Indicacion', 'Esperando respuesta de la llamada') self.app.addButton('Cancelar', self.cancel_call) self.app.stopSubWindow() # Lanzamos la subwindow self.app.showSubWindow(self.WAITING_WINDOW) return