__init__.py.old 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. #! /usr/bin/python3
  2. #
  3. ## LICENSE
  4. # This file is part of MyLibNetwork.
  5. #
  6. # MyLibNetwork is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # MyLibNetwork is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with MyLibNetwork. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. import logging
  20. import logging.handlers
  21. import os
  22. import queue
  23. import select
  24. import socket
  25. import sys
  26. import threading
  27. import time
  28. import traceback
  29. import trio
  30. lclient = logging.getLogger(__name__+".client")
  31. lserver = logging.getLogger(__name__+".server")
  32. lchat = logging.getLogger(__name__+".chat")
  33. class ConnHandlerBase(object):
  34. def __init__(self, socket, addr, server):
  35. self.status = "init"
  36. super(ConnHandlerBase, self).__init__()
  37. self.socket = socket
  38. self.addr = addr
  39. self.server = server
  40. self.block_size = 1024
  41. self.welcome_client()
  42. self.status="connected"
  43. def welcome_client(self):
  44. pass
  45. def handle(self, data_decoded):
  46. return
  47. def recv(self):
  48. try:
  49. data_received = self.socket.recv(self.block_size)
  50. data_decoded = data_received.decode("utf-8")
  51. if data_decoded:
  52. lchat.info(data_decoded.strip())
  53. self.handle(data_decoded)
  54. return True
  55. else:
  56. lserver.debug("connection corrupted")
  57. return False
  58. except Exception as e:
  59. lserver.error(e, exc_info=True)
  60. return False
  61. def send(self, msg):
  62. msg_encoded = bytes(msg, "utf-8")
  63. lchat.info("Server:"+msg)
  64. try:
  65. self.socket.send(msg_encoded)
  66. return True
  67. except Exception as e:
  68. lserver.error(e, exc_info=True)
  69. return False
  70. def close(self):
  71. self.status = "closed"
  72. try:
  73. self.socket.shutdown(0)
  74. except:
  75. lserver.error("error during socket shutdown, ignoring")
  76. try:
  77. self.socket.close()
  78. except:
  79. lserver.error("error closing socket, maybe already closed")
  80. class ConnHandlerEcho(ConnHandlerBase):
  81. def __init__(self, socket, addr, server):
  82. self.status = "init"
  83. self.super_class = super(ConnHandlerEcho, self)
  84. self.super_class.__init__(socket, addr, server)
  85. self.server = server
  86. def welcome_client(self):
  87. self.send("welcome to the client")
  88. def handle(self, data_decoded):
  89. lchat.info("Client:"+data_decoded)
  90. for h in list(set(self.server.connection_handler)-{self}):
  91. h.send(data_decoded)
  92. class Server(object):
  93. """docstring for SocketHandler"""
  94. def __init__(self,
  95. host,
  96. port=None,
  97. af_family="AF_INET",
  98. max_allowed_clients=5,
  99. handler=None,
  100. handler_kwargs={},
  101. ):
  102. super(Server, self).__init__()
  103. self.exit_event = False
  104. self.host=host
  105. self.port=port
  106. self.af_family = af_family
  107. self.handler_kwargs = handler_kwargs
  108. self.handler = handler
  109. self.max_allowed_clients = max_allowed_clients
  110. self.socket = self.make_socket()
  111. self.connection_handler = []
  112. self.conn_to_addr = {}
  113. self.addr_to_conn = {}
  114. self.conn_to_handler ={}
  115. self.handler_to_conn = {}
  116. self.read_sockets_expected = [self.socket]
  117. self.write_sockets_expected = []
  118. self.exc_sockets_expected = []
  119. def make_socket(self):
  120. lserver.debug("making a {} socket".format(self.af_family))
  121. if self.af_family == "AF_INET":
  122. return socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  123. elif self.af_family == "AF_UNIX":
  124. return socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
  125. else:
  126. raise ValueError(
  127. "AF_FAMILY '{}' not supported!".format(
  128. self.af_family
  129. )
  130. )
  131. def make_handler(self, conn, addr):
  132. return self.handler(conn, addr, self, **self.handler_kwargs)
  133. def register_conn(self, conn, addr):
  134. lserver.info(
  135. "New Connection, addr: '{}', socket: '{}'".format(addr,conn)
  136. )
  137. self.read_sockets_expected.append(conn)
  138. if addr:
  139. self.conn_to_addr[conn] = addr
  140. self.addr_to_conn[addr] = conn
  141. def unregister_conn(self, conn):
  142. self.read_sockets_expected.remove(conn)
  143. addr = self.conn_to_addr.get(conn, False)
  144. if addr:
  145. del self.addr_to_conn[addr]
  146. del self.conn_to_addr[conn]
  147. def register_handler(self, handler, conn):
  148. self.connection_handler.append(handler)
  149. self.conn_to_handler[conn] = handler
  150. self.handler_to_conn[handler] = conn
  151. def unregister_handler(self, handler, conn):
  152. self.connection_handler.remove(handler)
  153. del self.conn_to_handler[conn]
  154. del self.handler_to_conn[handler]
  155. def setup(self):
  156. lserver.info("setting up socket")
  157. if self.af_family == "AF_INET":
  158. self.socket.bind((self.host, self.port))
  159. elif self.af_family == "AF_UNIX":
  160. if os.path.exists(self.host):
  161. lserver.debug("file already exists")
  162. lserver.debug("attempting to remove it")
  163. os.remove(self.host)
  164. self.socket.bind(self.host)
  165. self.socket.listen(self.max_allowed_clients)
  166. # self.socket.settimeout(1)
  167. def run(self):
  168. self.setup()
  169. lserver.debug("entering main loop")
  170. while ( not self.exit_event ):
  171. # lserver.debug(self.read_sockets_expected)
  172. # lserver.debug(self.write_sockets_expected)
  173. # lserver.debug(self.exc_sockets_expected)
  174. read_sockets_confirmed, \
  175. write_sockets_confirmed, \
  176. exc_sockets_confirmed \
  177. = select.select(self.read_sockets_expected,
  178. self.write_sockets_expected,
  179. self.exc_sockets_expected,
  180. )
  181. lserver.debug("bleh")
  182. for s in read_sockets_confirmed:
  183. socket_handler = self.conn_to_handler.get(s, None)
  184. if ( s == self.socket ):
  185. lserver.debug("handling new client")
  186. conn, addr = self.socket.accept()
  187. handler = self.make_handler(conn, addr)
  188. self.register_conn(conn, addr)
  189. self.register_handler(handler, conn)
  190. elif ( socket_handler
  191. and (socket_handler in self.connection_handler) ):
  192. lserver.debug("handling client connection")
  193. try:
  194. if not socket_handler.recv():
  195. lserver.info("connection is broken, closing socket and removing it")
  196. self.unregister_handler(socket_handler, s)
  197. self.unregister_conn(conn)
  198. socket_handler.close()
  199. except Exception as e:
  200. lserver.error(e, exc_info=True)
  201. else:
  202. lserver.debug("else!")
  203. lserver.debug(socket_handler)
  204. time.sleep(1)
  205. def cleanup(self):
  206. pass
  207. class Client(threading.Thread):
  208. """docstring for Client"""
  209. is_connecting = False
  210. is_connected = False
  211. status = "uninitialized"
  212. def __init__(self,
  213. host,
  214. port=None,
  215. af_family="AF_INET",
  216. handle_data_func=None,
  217. error_handler=None,
  218. block_size=1024,
  219. ):
  220. self.super_class = super(Client, self)
  221. self.super_class.__init__()
  222. self.name = "Client"
  223. self.exit_event = False
  224. self.host = host
  225. self.port = port
  226. self.af_family = af_family
  227. self.block_size = block_size
  228. self.handle_data_func = handle_data_func
  229. self.is_connected = False
  230. self.error_handler = error_handler
  231. # self.socket = self.make_socket()
  232. self.socket = None
  233. self.status = "disconnected"
  234. def connect(self):
  235. self.status = "connecting"
  236. self.socket = self.make_socket()
  237. lclient.info(
  238. "connecting to socket '{}' of type {}".format(
  239. self.host,
  240. self.af_family
  241. )
  242. )
  243. try:
  244. if self.af_family == "AF_INET":
  245. self.socket.connect((self.host, self.port))
  246. elif self.af_family == "AF_UNIX":
  247. if os.path.exists(self.host):
  248. self.socket.connect(self.host)
  249. else:
  250. lclient.warn("File not found. Aborting.")
  251. return
  252. self.is_connected = True
  253. self.status = "connected"
  254. lclient.info("connected")
  255. return True
  256. except Exception as e:
  257. lclient.debug(e, exc_info=True)
  258. if type(e) is ConnectionRefusedError:
  259. lclient.info("failed to connect to socket '{}'".format(self.host))
  260. self.disconnect()
  261. return False
  262. def disconnect(self):
  263. lclient.info("disconnecting from socket '{}'".format(self.host))
  264. self.is_connected = False
  265. self.status = "disconnected"
  266. if self.socket:
  267. try:
  268. self.socket.shutdown(socket.SHUT_RDWR)
  269. except Exception as e:
  270. lclient.error(e)
  271. try:
  272. self.socket.close()
  273. except Exception as e:
  274. lclient.error("error occured while closing the socket, " +
  275. "maybe it is already closed",exc_info=e)
  276. del self.socket
  277. self.socket = None
  278. def handle_data(self, data_received):
  279. data_decoded = data_received.decode("utf-8")
  280. lchat.info("Server: "+data_decoded)
  281. if self.handle_data_func:
  282. try:
  283. self.handle_data_func(data_decoded)
  284. except Exception as e:
  285. lclient.error(e, exc_info=True)
  286. def is_running(self):
  287. return (self in threading.enumerate())
  288. def make_socket(self):
  289. lclient.info("creating a {} socket".format(self.af_family))
  290. if self.af_family == "AF_INET":
  291. s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  292. elif self.af_family == "AF_UNIX":
  293. s = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
  294. else:
  295. raise ValueError(
  296. "AF_FAMILY '{}' not supported!".format(
  297. self.af_family
  298. )
  299. )
  300. return s
  301. def main_loop(self):
  302. lclient.debug("starting main loop")
  303. while ( not self.exit_event ):
  304. if not self.status in ["connected"]:
  305. time.sleep(0.1)
  306. continue
  307. # print(0)
  308. read_confirmed, write_confirmed, exc_confirmed \
  309. = select.select(
  310. [self.socket],
  311. [],
  312. [self.socket],
  313. 1
  314. )
  315. if self.socket in exc_confirmed:
  316. self.is_connected = False
  317. lclient.warning("socket is expected to corrupt, exiting")
  318. self.disconnect()
  319. # self.stop()
  320. break
  321. elif self.socket in read_confirmed:
  322. try:
  323. data_received = self.read_from_socket()
  324. if data_received == b'':
  325. lclient.info("connection is broken, closing socket exiting")
  326. self.disconnect()
  327. # self.stop()
  328. # break
  329. else:
  330. self.handle_data(data_received)
  331. except Exception as e:
  332. lclient.error(e, exc_info=True)
  333. if type(e) is OSError:
  334. self.is_connected = False
  335. lclient.warn("connection broken, exiting")
  336. self.disconnect()
  337. # self.stop()
  338. # break
  339. else:
  340. raise
  341. else:
  342. time.sleep(0.1)
  343. def read_from_socket(self):
  344. data_received = self.socket.recv(self.block_size)
  345. return data_received
  346. def run(self):
  347. # self.connect()
  348. if self.error_handler:
  349. self.error_handler(self.main_loop)
  350. else:
  351. self.main_loop()
  352. def send(self, msg):
  353. msg = msg.rstrip()
  354. msg_encoded = bytes(msg+"\r\n", "utf-8")
  355. try:
  356. lchat.info("Client: "+msg)
  357. self.socket.send(msg_encoded)
  358. except Exception as e:
  359. self.is_connected = False
  360. lclient.error(e, exc_info=True)
  361. self.status = "shutdown"
  362. def setup(self):
  363. pass
  364. def stop(self,reason=None):
  365. self.disconnect()
  366. self.exit_event = True
  367. if reason:
  368. print(reason)
  369. class Client(threading.Thread):
  370. """docstring for Client"""
  371. is_connecting = False
  372. is_connected = False
  373. status = "uninitialized"
  374. def __init__(self,
  375. host,
  376. port=None,
  377. af_family="AF_INET",
  378. handle_data_func=None,
  379. error_handler=None,
  380. block_size=1024,
  381. ):
  382. self.super_class = super(Client, self)
  383. self.super_class.__init__()
  384. self.name = "Client"
  385. self.exit_event = False
  386. self.host = host
  387. self.port = port
  388. self.af_family = af_family
  389. self.block_size = block_size
  390. self.handle_data_func = handle_data_func
  391. self.is_connected = False
  392. self.error_handler = error_handler
  393. # self.socket = self.make_socket()
  394. self.socket = None
  395. self.status = "disconnected"
  396. def connect(self):
  397. self.status = "connecting"
  398. self.socket = self.make_socket()
  399. lclient.info(
  400. "connecting to socket '{}' of type {}".format(
  401. self.host,
  402. self.af_family
  403. )
  404. )
  405. try:
  406. if self.af_family == "AF_INET":
  407. self.socket.connect((self.host, self.port))
  408. elif self.af_family == "AF_UNIX":
  409. if os.path.exists(self.host):
  410. self.socket.connect(self.host)
  411. else:
  412. lclient.warn("File not found. Aborting.")
  413. return
  414. self.is_connected = True
  415. self.status = "connected"
  416. lclient.info("connected")
  417. return True
  418. except Exception as e:
  419. lclient.debug(e, exc_info=True)
  420. if type(e) is ConnectionRefusedError:
  421. lclient.info("failed to connect to socket '{}'".format(self.host))
  422. self.disconnect()
  423. return False
  424. def disconnect(self):
  425. lclient.info("disconnecting from socket '{}'".format(self.host))
  426. self.is_connected = False
  427. self.status = "disconnected"
  428. if self.socket:
  429. try:
  430. self.socket.shutdown(socket.SHUT_RDWR)
  431. except Exception as e:
  432. lclient.error(e)
  433. try:
  434. self.socket.close()
  435. except Exception as e:
  436. lclient.error("error occured while closing the socket, " +
  437. "maybe it is already closed",exc_info=e)
  438. del self.socket
  439. self.socket = None
  440. def handle_data(self, data_received):
  441. data_decoded = data_received.decode("utf-8")
  442. lchat.info("Server: "+data_decoded)
  443. if self.handle_data_func:
  444. try:
  445. self.handle_data_func(data_decoded)
  446. except Exception as e:
  447. lclient.error(e, exc_info=True)
  448. def is_running(self):
  449. return (self in threading.enumerate())
  450. def make_socket(self):
  451. lclient.info("creating a {} socket".format(self.af_family))
  452. if self.af_family == "AF_INET":
  453. s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  454. elif self.af_family == "AF_UNIX":
  455. s = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
  456. else:
  457. raise ValueError(
  458. "AF_FAMILY '{}' not supported!".format(
  459. self.af_family
  460. )
  461. )
  462. return s
  463. def main_loop(self):
  464. lclient.debug("starting main loop")
  465. while ( not self.exit_event ):
  466. if not self.status in ["connected"]:
  467. time.sleep(0.1)
  468. continue
  469. # print(0)
  470. read_confirmed, write_confirmed, exc_confirmed \
  471. = select.select(
  472. [self.socket],
  473. [],
  474. [self.socket],
  475. 1
  476. )
  477. if self.socket in exc_confirmed:
  478. self.is_connected = False
  479. lclient.warning("socket is expected to corrupt, exiting")
  480. self.disconnect()
  481. # self.stop()
  482. break
  483. elif self.socket in read_confirmed:
  484. try:
  485. data_received = self.read_from_socket()
  486. if data_received == b'':
  487. lclient.info("connection is broken, closing socket exiting")
  488. self.disconnect()
  489. # self.stop()
  490. # break
  491. else:
  492. self.handle_data(data_received)
  493. except Exception as e:
  494. lclient.error(e, exc_info=True)
  495. if type(e) is OSError:
  496. self.is_connected = False
  497. lclient.warn("connection broken, exiting")
  498. self.disconnect()
  499. # self.stop()
  500. # break
  501. else:
  502. raise
  503. else:
  504. time.sleep(0.1)
  505. def read_from_socket(self):
  506. data_received = self.socket.recv(self.block_size)
  507. return data_received
  508. def run(self):
  509. # self.connect()
  510. if self.error_handler:
  511. self.error_handler(self.main_loop)
  512. else:
  513. self.main_loop()
  514. def send(self, msg):
  515. msg = msg.rstrip()
  516. msg_encoded = bytes(msg+"\r\n", "utf-8")
  517. try:
  518. lchat.info("Client: "+msg)
  519. self.socket.send(msg_encoded)
  520. except Exception as e:
  521. self.is_connected = False
  522. lclient.error(e, exc_info=True)
  523. self.status = "shutdown"
  524. def setup(self):
  525. pass
  526. def stop(self,reason=None):
  527. self.disconnect()
  528. self.exit_event = True
  529. if reason:
  530. print(reason)
  531. #