Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.34 KB | None | 0 0
  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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement