Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import select
- import socket
- import re
- import threading
- import signal
- from comms import send, receive
- from Crypto.PublicKey import RSA
- from Crypto.Signature import PKCS1_PSS
- from Crypto.Hash import SHA
- clients = list()
- rooms = list()
- HOST = "127.0.0.1"
- PORT = 5000
- class Client(object):
- clientCountOnline=0
- def __init__(self, socket, address, pubkey):
- """Constructor"""
- self.sock = socket
- self.addr = address
- self.pubkey = pubkey
- self.room = None
- self.name = None
- Client.clientCountOnline += 1
- thread = threading.Thread(target=self.run, args=())
- thread.daemon = True
- self._is_online = True
- thread.start()
- def run(self):
- try:
- message = receive(self.sock)
- name = self.desencriptar(message)
- name = name.split(' ',1)[0].capitalize()
- #name = self.sock.recv(1024).strip().capitalize()
- except socket.error as e:
- print e
- while name in [client.name for client in clients]:
- self.sock.send("El nom ja esta en us.\n")
- name = self.sock.recv(1024).strip().capitalize()
- self.name = name
- message = self.encriptar('[SERVIDOR] Benvingut/da %s!' % self.name, self)
- #self.sock.send(message)
- send(self.sock, message)
- #self.sock.send('[SERVIDOR] Benvingut/da %s!' % self.name)
- print "* Usuari %s s'ha connectat" % name
- self.send_all("+++ L'usuari %s s'acaba de connectar" % self.name)
- while (self._is_online):
- #message = self.sock.recv(1024)
- message = receive(self.sock)
- message = self.desencriptar(message)
- if not message:
- print "* Usuari %s s'ha desconnectat" % self.name
- clients.remove(self)
- Client.clientCountOnline -= 1
- self.stop()
- elif message.lower().startswith('/mostra_tots'):
- self.mostra_tots()
- elif message.startswith("@"):
- recip_name = re.findall(r"(?<=@)(\b\w*\b)", message)[0]
- if not self.send_private_msg(message):
- print "* Error: usuari %s offline -> %s" % (recip_name, self.name)
- self.sock.send("[SERVIDOR] ERROR: usuari %s offline" % recip_name)
- elif message.lower().startswith("/mostra_canals"):
- self.mostra_canals()
- elif message.lower().startswith("/help"):
- self.print_help()
- elif message.lower().startswith("/crea"):
- new_room_name = self.crea_canal(message)
- if new_room_name:
- self.sock.send('========================================================\n')
- self.sock.send('[SERVIDOR] Acabes d\'unir-te al canal %s' % (new_room_name,))
- print '* Nou canal %s' % new_room_name
- else:
- self.sock.send('[SERVIDOR] No s\'ha pogut crear el canal :(')
- print '* Error al crear un canal de %s' % (self.name)
- elif message.lower().startswith("/surt"):
- room_to_leave = self.surt_canal()
- if room_to_leave:
- self.sock.send('[SERVIDOR] Acabes d\'abandonar el canal %s' % (room_to_leave,))
- self.sock.send('========================================================\n')
- print '* %s surt del canal %s' % (self.name, room_to_leave, )
- else:
- self.sock.send('[SERVIDOR] No s\'ha pogut realitzar la operacio :(')
- print '* Error de %s al fer command surt canal' % (self.name)
- elif message.lower().startswith("/canvia"):
- room_to_join = self.canvia_canal(message)
- if room_to_join:
- self.sock.send('========================================================\n')
- self.sock.send('[SERVIDOR] T\'acabes de canviar al canal %s' % (room_to_join,))
- print '* %s canvia al canal %s' % (self.name, room_to_join, )
- else:
- self.sock.send('[SERVIDOR] No s\'ha pogut realitzar la operacio :(')
- print '* Error de %s al fer command surt canal' % (self.name)
- elif message.lower().startswith("/esborra"):
- room_to_remove = self.borra_canal(message)
- if room_to_remove:
- self.sock.send('[SERVIDOR] Acabes d\'esborrar el canal %s' % (room_to_remove,))
- print '* Canal %s esborrat per %s' % (room_to_remove, self.name, )
- else:
- self.sock.send('[SERVIDOR] No s\'ha pogut esborrar, ets el propietari del canal?')
- print '* Error de %s al fer command esborrar canal' % (self.name)
- elif message.lower().startswith("/mostra_usuaris"):
- if not self.room:
- self.sock.send("[SERVIDOR] No estas a cap sala")
- else:
- self.mostra_usuaris_canal()
- elif message.lower().startswith("/"):
- self.sock.send("[SERVIDOR] %s no es cap comanda" % message)
- else:
- if self.room:
- message = "[" + self.name + " a " + self.room.name + "]" + " " + message
- print message
- self.send_room(message)
- else:
- message = "["+self.name+"]" + " " + message
- print message
- self.send_all_no_room(message)
- def encriptar(self, message, to_who):
- try:
- encryptor = to_who.pubkey
- encrypted_message = encryptor.encrypt(message, 0)
- return encrypted_message[0]
- except IOError:
- return 'PLAIN: No s\'ha pogut trobat la clau publica per %s' % to_who.name
- def desencriptar(self, message):
- dataparts = message.split('#^[[')
- signature = dataparts[1]
- message = dataparts[0]
- verified = self.verify_signature(message, signature)
- message = server_privkey.decrypt(message)
- if message != '\x00':
- if verified:
- message = '%s [OK]' % message
- else:
- message = '%s [No verificat]' % message
- return message
- def verify_signature(self, message, signature):
- try:
- key = self.pubkey
- msg_hash = SHA.new()
- msg_hash.update(message)
- verifier = PKCS1_PSS.new(key)
- return verifier.verify(msg_hash, signature)
- except IOError:
- return False
- def send_private_msg(self, message):
- """Method to send a private message with @ handle
- regex finds recipient name after @ handle
- r"(?<=@)(\b\w*\b)" means whole word after @
- tries to send the message, if user not found = offline
- """
- recip_name = re.findall(r"(?<=@)(\b\w*\b)", message)[0]
- exp = re.compile(r'^@(\b\w*\b)')
- message = exp.sub("", message)
- for client in clients:
- if client.name == recip_name:
- message = "[" + self.name + " to " + client.name + "]" + message
- client.sock.send(message)
- print message
- return True
- return False
- def mostra_tots(self):
- """Show all users online at a moment
- """
- message = '[SERVIDOR] Usuaris online: '
- message += ', '.join([client.name for client in clients])
- self.sock.send(message)
- def send_all(self, message):
- """Send to all method, broadcast a message"""
- for sock in [client.sock for client in clients]:
- if sock != self.sock:
- message_encripted = self.encriptar(message,client)
- send(sock,message_encripted)
- #sock.send(message)
- def send_all_no_room(self, message):
- """Send to all method, broadcast a message"""
- for sock in [client.sock for client in clients]:
- if sock != self.sock and not client.room:
- message_encripted = self.encriptar(message,client)
- send(sock,message_encripted)
- #sock.send(message)
- def crea_canal(self, new_room_name):
- """Create a new room and join
- regex expression ^([^\s]*)(\s) -> group of 1st word and whitespace"""
- exp = re.compile(r'^([^\s]*)(\s)')
- new_room_name = exp.sub("", new_room_name)
- if not new_room_name in [room.name for room in rooms]:
- self.room = Room(new_room_name, self)
- rooms.append( self.room )
- self.send_all('+++ %s acaba de crear el canal %s' % (self.name, new_room_name, ))
- return new_room_name
- else:
- return None
- def mostra_canals(self):
- """Show all created rooms to chat"""
- message = '[SERVIDOR] Canals online: '
- message += ', '.join([room.name for room in rooms])
- if not [room for room in rooms]:
- self.sock.send("[SERVIDOR] No hi ha canals online creats")
- else:
- self.sock.send(message)
- def surt_canal(self):
- """Exit from a chat room"""
- removed = None
- for room in rooms:
- if self in room.clients_in_room:
- room.remove_client(self)
- self.room = None
- removed = room.name
- return removed
- def canvia_canal(self, room_to_join):
- exp = re.compile(r'^([^\s]*)(\s)')
- room_to_join = exp.sub("", room_to_join)
- if not room_to_join in [room.name for room in rooms]:
- self.sock.send('[SERVIDOR] El canal %s no existeix' % (room_to_join,))
- return None
- for room in rooms:
- if self in room.clients_in_room:
- room.remove_client(self)
- if room.name == room_to_join:
- room.add_client(self)
- self.room = room
- return room_to_join
- def borra_canal(self, room_to_remove):
- exp = re.compile(r'^([^\s]*)(\s)')
- room_to_remove = exp.sub("", room_to_remove)
- if not room_to_remove in [room.name for room in rooms]:
- self.sock.send('[SERVIDOR] El canal %s no existeix' % (room_to_remove,))
- return None
- removed = None
- for this_room in rooms:
- if this_room.name == room_to_remove and this_room.creator == self:
- for client in [client for client in this_room.clients_in_room]:
- this_room.remove_client(client)
- if self.sock != client.sock:
- client.sock.send('[SERVIDOR] El canal %s ha sigut esborrat' % (this_room.name))
- client.room = None
- removed = this_room.name
- rooms.remove(this_room)
- del this_room
- return removed
- def mostra_usuaris_canal(self):
- message = '[SERVIDOR] Usuaris online: '
- message += ', '.join([client.name for client in self.room.clients_in_room])
- self.sock.send(message)
- def send_room(self, message):
- for sock in [client.sock for client in self.room.clients_in_room]:
- if sock != self.sock:
- sock.send(message)
- def print_help(self):
- self.sock.send("""
- **************************************************************
- ** HELP - Commands **
- ** **
- ** 1. /CREA "nom_canal": crear canal **
- ** 2. /CANVIA "nom_canal": canviar a canal **
- ** 3. /SURT : sortir del canal actual **
- ** 4. /ESBORRA "nom_canal": esborrar un canal **
- ** 5. /MOSTRA_CANALS: mostrar canals online **
- ** 6. /MOSTRA_USUARIS: mostrar usuaris en el canal actual **
- ** 7. /MOSTRA_TOTS: mostrar usuaris en tots els canals **
- ** 8. @usuari "missatge": enviar missatge privat **
- ** 9. /EXIT: sortir del xat **
- ** **
- ** *Nota sobre l'encriptacio: aquest xat esta encriptat, **
- ** al final d'un missatge es mostra [OK] si aquest ha **
- ** estat correctament encriptat. **
- **************************************************************
- """)
- def stop(self):
- """Method to let Client thread die"""
- self._is_online = False
- class Room(object):
- """docstring for Room."""
- def __init__(self, name, creator):
- self.name = name
- self.clients_in_room = list()
- self.clients_in_room.append(creator)
- self.creator = creator #Client class object
- def remove_client(self, client):
- self.clients_in_room.remove(client)
- def add_client(self, client):
- self.clients_in_room.append(client)
- def sighandler(signum, f):
- print 'Apagant el servidor del xat...'
- for client in clients:
- client.sock.close()
- sckt.close()
- # Set up the listening socket
- sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sckt.bind((HOST, PORT))
- print 'Generant claus RSA...'
- server_privkey = RSA.generate(1024, os.urandom)
- server_pubkey = server_privkey.publickey()
- sckt.listen(10)
- print "Servidor escoltant a %s esperant usuaris..." % ("%s:%s" % sckt.getsockname())
- signal.signal(signal.SIGINT, sighandler)
- # Accepting connections in a loop
- while True:
- (ready_to_read, _, _) = select.select([sckt] + [client.sock for client in clients], [], [])
- for connection in ready_to_read:
- if connection == sckt:
- (connection, address) = sckt.accept()
- #pubkey = RSA.importKey(connection.recv(1024))
- pubkey = RSA.importKey( receive(connection) )
- #connection.send(server_pubkey.exportKey())
- send(connection, server_pubkey.exportKey() )
- clients.append( Client(connection, address, pubkey) )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement