SHARE
TWEET

Untitled

a guest Oct 21st, 2019 77 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python3
  2. from socket import \
  3.     socket, \
  4.     AF_INET, \
  5.     SOCK_STREAM, \
  6.     SOL_SOCKET, \
  7.     SO_REUSEADDR
  8. from selectors import DefaultSelector, EVENT_READ
  9. from sys import argv, stderr
  10. from threading import Thread
  11. from types import SimpleNamespace
  12. from os.path import isfile
  13.  
  14.  
  15. def eprint(*args, **kwargs):
  16.     print(file=stderr, *args, **kwargs)
  17.  
  18.  
  19. clients = []
  20.  
  21.  
  22. def remove_client(name):
  23.     global clients
  24.     clients = list(filter(lambda c: c.name != name, clients))
  25.  
  26.  
  27. class Dispatcher(Thread):
  28.  
  29.     def __init__(self, arguments, selector):
  30.         """
  31.         Create a master socket on a specific interface and port,
  32.         if the interface is '_' then listen on all of the available
  33.         """
  34.         super().__init__(daemon=True)
  35.         if len(arguments) < 3:
  36.             eprint('Not enough arguments\n'
  37.                    'Usage:\n'
  38.                    'alice interface port\n')
  39.             raise Exception
  40.         try:
  41.             port = int(arguments[2])
  42.         except ValueError:
  43.             eprint('Non-int port is given')
  44.             raise ValueError
  45.         interface = arguments[1] if arguments[1] != '_' else ''
  46.         self.selector = selector
  47.         self.info = (interface, port)
  48.         self.sock = socket(AF_INET, SOCK_STREAM)
  49.         self.sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)  # Turn on address reuse
  50.  
  51.     def run(self):
  52.         self.sock.bind(self.info)
  53.         self.sock.listen()
  54.         next_name = 1
  55.         while True:
  56.             con, addr = self.sock.accept()
  57.             con.setblocking(False)
  58.             name = 'u' + str(next_name)
  59.             client = SimpleNamespace(name=name, current_file='', outb='')
  60.             clients.append(client)
  61.             self.selector.register(con, EVENT_READ, data=client)  # Available only for writing
  62.             print(f'New CIR is accepted from {str(addr)}')
  63.  
  64.  
  65. class Server(Thread):
  66.     """
  67.     Handle all incoming connections
  68.     """
  69.  
  70.     def __init__(self, selector):
  71.         super().__init__()
  72.         self.selector = selector
  73.  
  74.     @staticmethod
  75.     def _gen_filename(filename):
  76.         postfix = ''
  77.         i = 0
  78.         while isfile(filename + postfix):
  79.             postfix = str(i)
  80.             i += 1
  81.         filename += str(postfix)
  82.         return filename
  83.  
  84.     @staticmethod
  85.     def _write_file(filename, data):
  86.         f = open(filename, 'ab')
  87.         f.write(data)
  88.         f.close()
  89.  
  90.     def _read(self, sock, client):
  91.         data = sock.recv(1024)
  92.         if not client.current_file and data:
  93.             client.current_file = self._gen_filename(data.decode())
  94.         else:
  95.             self._write_file(client.current_file, data)
  96.  
  97.         if not data:
  98.             self._close(sock, client)
  99.             return
  100.  
  101.     def _close(self, sock, client):
  102.         remove_client(client.name)
  103.         self.selector.unregister(sock)
  104.         sock.close()
  105.         print(f'{client.name} disconnected')
  106.  
  107.     def run(self):
  108.         while True:
  109.             events = self.selector.select(timeout=None)
  110.             for key, mask in events:
  111.                 sock = key.fileobj
  112.                 client = key.data
  113.                 if mask & EVENT_READ:
  114.                     self._read(sock, client)
  115.  
  116.  
  117. def main():
  118.     selector = DefaultSelector()
  119.     Server(selector).start()
  120.     dispatcher = Dispatcher(argv, selector)
  121.     dispatcher.run()
  122.     dispatcher.join()
  123.     print('All joined')  # Never goes here
  124.  
  125.  
  126. if __name__ == '__main__':
  127.     main()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top