AntonPaly4

server

Aug 19th, 2018
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.81 KB | None | 0 0
  1. """ Simple echo-server_src. Making socket. Forwarding messages from clients to every-listening.
  2.        Takes ADDRESS and PORT to listen from on initialisation as required.
  3.        Takes time_out=0.2, buf_size=2048, max_clients=15, code_format='UTF-8' as not required."""
  4.  
  5. from socket import socket, AF_INET, SOCK_STREAM, timeout
  6. from os import urandom
  7. from queue import Queue
  8. from threading import Thread
  9.  
  10. from server_src.handlers import StorageHandler
  11. from server_src.user_exceptions import *
  12. from server_src.models import my_session
  13.  
  14. from JIM.JIMs import Jim, MessageConverter
  15. from JIM.jim_config import *
  16. from crypto.crypto import *
  17.  
  18.  
  19. class Server:
  20.     """ Simple echo-server_src. Making socket. Forwarding messages from clients to every-listening.
  21.        Takes ADDRESS and PORT to listen from on initialisation as required.
  22.        Takes time_out=0.2, buf_size=2048, max_clients=15, code_format='UTF-8' as not required"""
  23.  
  24.     def __init__(self, address, port_, time_out=0.2, buf_size=2048, max_clients=15, code_format='UTF-8'):
  25.         """ :param address: address to listen from, :type: string, example '192.168.1.1'
  26.            :param port_: port to listen from, :type: int, example 7777
  27.        """
  28.         self.addr = address, port_
  29.  
  30.         self.soc = None
  31.  
  32.         # через гуй добавить возможность отключать
  33.         self._is_alive = False
  34.  
  35.         self.chats_messages = Queue()
  36.         self.addressed_messages = Queue()
  37.  
  38.         self.connected_clients = []
  39.         self.authorised_clients = []
  40.         self.online_users = {}
  41.  
  42.         self.converter = MessageConverter()
  43.         self.handler = ServerHandler(self.connected_clients, self.authorised_clients, self.online_users,
  44.                                      self.addressed_messages, self.chats_messages)
  45.  
  46.         self._timeout = time_out
  47.         self._buf_size = buf_size
  48.         self._clients_count = max_clients
  49.         self._code_format = code_format
  50.  
  51.         self.addressed_messages_thread = Thread(target=self.send_addressed_messages)
  52.         self.chat_messages_thread = Thread(target=self.send_chat_messages)
  53.  
  54.     def listen(self):
  55.         """ To make socket using initialised parameters"""
  56.         self.soc = socket(AF_INET, SOCK_STREAM)
  57.         self.soc.bind(self.addr)
  58.         self.soc.settimeout(self._timeout)
  59.         self.soc.listen(self._clients_count)
  60.  
  61.     def send_chat_messages(self):
  62.         """ Method to use in thread to send chat-messages. """
  63.         while self._is_alive:
  64.             try:
  65.                 message = self.chats_messages.get()
  66.             except:
  67.                 pass
  68.             else:
  69.                 bmessage = self.converter(message)
  70.                 for user in self.online_users.values():
  71.                     user.send(bmessage)
  72.  
  73.     def send_addressed_messages(self):
  74.         """ To send addressed messages, tacking message from queue and sending it if user is on-line,
  75.        if not - puts it back to queue"""
  76.         while self._is_alive:
  77.             try:
  78.                 message = self.addressed_messages.get()
  79.             except:
  80.                 pass
  81.             else:
  82.                 recipient = message[TO]
  83.                 print(message, '-----', recipient)
  84.                 conn = self.online_users.get(recipient)
  85.                 print(conn)
  86.                 if conn:
  87.                     message_ = self.converter(message)
  88.                     conn.send(message_)
  89.                     print('sended -> ', message)
  90.                 else:
  91.                     # TODO: в базу и ставить пометку не доставлено а при коннекте проверять есть ли не доставленные
  92.                     # а то потеряются если сервер упадет
  93.                     self.addressed_messages.put(message)
  94.  
  95.     def _accept(self):
  96.         """ Handle every connected user. """
  97.         try:
  98.             conn, addr = self.soc.accept()
  99.         except OSError:
  100.             pass
  101.         else:
  102.             self.connected_clients.append(conn)
  103.             Thread(target=self.handle_conn, args=(conn,)).start()
  104.  
  105.     def handle_conn(self, conn):
  106.         """
  107.        Using in thread to receive every request from certain user and initiate handling of each.
  108.        :param conn: - socket of connected user :type: socket.
  109.        """
  110.         while conn in self.connected_clients:
  111.             try:
  112.                 message = conn.recv(self._buf_size)
  113.             except timeout:
  114.                 pass
  115.             else:
  116.                 if message:
  117.                     self.handler.handle(message, conn)
  118.  
  119.  
  120.     def run(self):
  121.         """ To start server_src working. """
  122.         self._is_alive = True
  123.         self.listen()
  124.         self.addressed_messages_thread.start()
  125.         self.chat_messages_thread.start()
  126.         while True:
  127.             self._accept()
  128.  
  129.  
  130. class ServerHandler:
  131.     def __init__(self, connected_clients, authorised_clients, online_users, addressed_messages, chat_messages):
  132.         self.connected_clients = connected_clients
  133.         self.authorised_clients = authorised_clients
  134.         self.online_users = online_users
  135.  
  136.         self.chats_messages = chat_messages
  137.         self.addressed_messages = addressed_messages
  138.  
  139.         self.storage_handler = StorageHandler(my_session)
  140.         self.converter = MessageConverter()
  141.         self.responder = Jim()
  142.  
  143.     def authorise(self, user, conn):
  144.         word = b64encode(urandom(32)).decode('utf-8')
  145.         request = self.responder.create(response=OK, alert=word)
  146.         request = self.converter(request)
  147.         conn.send(request)
  148.         cl_answ = conn.recv(1024)
  149.         cl_answ = self.converter(cl_answ)
  150.         answ = cl_answ[ANSWER]
  151.         key = self.storage_handler.get_password(user)
  152.         if key and check_word(key, answ, word):
  153.             resp_ = self.responder.create(response=OK, alert='authorised')
  154.             self.authorised_clients.append(conn)
  155.         else:
  156.             resp_ = self.responder.create(response=WRONG_LOGIN_INFO, alert=WRONG_LOGIN_OR_PASSWORD)
  157.         return resp_
  158.  
  159.     def registration(self, user, password, conn):
  160.         try:
  161.             self.storage_handler.registration(user, password)
  162.         except UserAlreadyExists:
  163.             resp, alert = CONFLICT, ALREADY_EXISTS
  164.         else:
  165.             resp, alert = OK, ADDED
  166.         response = self.responder.create(response=resp, alert=alert)
  167.         self.authorised_clients.append(conn)
  168.         return response
  169.  
  170.     def check_authorisation(self, conn):
  171.         if conn in self.authorised_clients:
  172.             return True
  173.         else:
  174.             resp = self.responder.create(response=NOT_AUTHORISED)
  175.             resp = self.converter(resp)
  176.             conn.send(resp)
  177.             # time.sleep(0.2)
  178.             conn.close()
  179.             return False
  180.  
  181.     def get_contacts(self, user):
  182.         quantity = self.storage_handler.count_contacts(user)
  183.         contact_list = self.storage_handler.get_contacts(user)
  184.         resp_ = self.responder.create(action=CONTACT_LIST, quantity=quantity, contact_list=contact_list)
  185.         return resp_
  186.  
  187.     def add_contact(self, user, contact):
  188.         try:
  189.             self.storage_handler.add_contact(user, contact)
  190.         except ContactAlreadyInList:
  191.             resp, alert = CONFLICT, ALREADY_IN_LIST
  192.         except UserNotExisting:
  193.             resp, alert = NOT_FOUND, USER_NOT_EXISTS
  194.         except SelfAdding:
  195.             resp, alert = CONFLICT, TRYING_TO_ADD_SELF
  196.         else:
  197.             resp, alert = OK, ADDED
  198.         response = self.responder.create(response=resp, alert=alert)
  199.         return response
  200.  
  201.     def del_contact(self, user, contact):
  202.         try:
  203.             self.storage_handler.del_contact(user, contact)
  204.         except ContactNotInList:
  205.             resp, alert = NOT_FOUND, CONTACT_NOT_IN_LIST
  206.         else:
  207.             resp, alert = OK, REMOVED
  208.         response = self.responder.create(response=resp, alert=alert)
  209.         return response
  210.  
  211.     def presence(self, user, conn):
  212.         self.storage_handler.presence(user, conn.getsockname()[0])
  213.         self.online_users[user] = conn
  214.  
  215.     def unknown_action(self):
  216.         resp = self.responder.create(response=WRONG_REQUEST, alert=UNKNOWN_ACTION)
  217.         return resp
  218.  
  219.     def income_message(self, message):
  220.         if message[TO].startswith('#'):
  221.             self.chats_messages.put(message)
  222.         else:
  223.             self.addressed_messages.put(message)
  224.  
  225.     def quit(self, user):
  226.         conn_ = self.online_users.pop(user)
  227.         self.connected_clients.remove(conn_)
  228.         self.authorised_clients.remove(conn_)
  229.         conn_.close()
  230.  
  231.     def handle(self, message, conn):
  232.         message = self.converter(message)
  233.         print(message)
  234.         action = message.get(ACTION)
  235.         resp = None
  236.         if action != AUTHORISE and action != REGISTER:
  237.             self.check_authorisation(conn)
  238.  
  239.         if action == MSG:
  240.             self.income_message(message)
  241.         elif action == PRESENCE:
  242.             self.presence(message[USER], conn)
  243.         elif action == GET_CONTACTS:
  244.             resp = self.get_contacts(message[USER])
  245.         elif action == ADD_CONTACT:
  246.             resp = self.add_contact(message[USER], message[CONTACT])
  247.         elif action == DEL_CONTACT:
  248.             resp = self.del_contact(message[USER], message[CONTACT])
  249.         elif action == AUTHORISE:
  250.             resp = self.authorise(message[USER], conn)
  251.         elif action == REGISTER:
  252.             resp = self.registration(message[USER], message[PASSWORD], conn)
  253.         elif action == QUIT:
  254.             self.quit(message[USER])
  255.         else:
  256.             resp = self.unknown_action()
  257.         if resp:
  258.             response = self.converter(resp)
  259.             conn.send(response)
  260.  
  261.  
  262. if __name__ == '__main__':
  263.     server = Server('', 7777)
  264.     server.run()
Add Comment
Please, Sign In to add comment