RawServer.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. # Written by Bram Cohen
  2. # see LICENSE.txt for license information
  3. from bisect import insort
  4. from SocketHandler import SocketHandler, UPnP_ERROR
  5. import socket
  6. from cStringIO import StringIO
  7. from traceback import print_exc
  8. from select import error
  9. from threading import Thread, Event
  10. from time import sleep
  11. from clock import clock
  12. import sys
  13. try:
  14. True
  15. except:
  16. True = 1
  17. False = 0
  18. def autodetect_ipv6():
  19. try:
  20. assert sys.version_info >= (2,3)
  21. assert socket.has_ipv6
  22. socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
  23. except:
  24. return 0
  25. return 1
  26. def autodetect_socket_style():
  27. if sys.platform.find('linux') < 0:
  28. return 1
  29. else:
  30. try:
  31. f = open('/proc/sys/net/ipv6/bindv6only','r')
  32. dual_socket_style = int(f.read())
  33. f.close()
  34. return int(not dual_socket_style)
  35. except:
  36. return 0
  37. READSIZE = 32768
  38. class RawServer:
  39. def __init__(self, doneflag, timeout_check_interval, timeout, noisy = True,
  40. ipv6_enable = True, failfunc = lambda x: None, errorfunc = None,
  41. sockethandler = None, excflag = Event()):
  42. self.timeout_check_interval = timeout_check_interval
  43. self.timeout = timeout
  44. self.servers = {}
  45. self.single_sockets = {}
  46. self.dead_from_write = []
  47. self.doneflag = doneflag
  48. self.noisy = noisy
  49. self.failfunc = failfunc
  50. self.errorfunc = errorfunc
  51. self.exccount = 0
  52. self.funcs = []
  53. self.externally_added = []
  54. self.finished = Event()
  55. self.tasks_to_kill = []
  56. self.excflag = excflag
  57. if sockethandler is None:
  58. sockethandler = SocketHandler(timeout, ipv6_enable, READSIZE)
  59. self.sockethandler = sockethandler
  60. self.add_task(self.scan_for_timeouts, timeout_check_interval)
  61. def get_exception_flag(self):
  62. return self.excflag
  63. def _add_task(self, func, delay, id = None):
  64. assert float(delay) >= 0
  65. insort(self.funcs, (clock() + delay, func, id))
  66. def add_task(self, func, delay = 0, id = None):
  67. assert float(delay) >= 0
  68. self.externally_added.append((func, delay, id))
  69. def scan_for_timeouts(self):
  70. self.add_task(self.scan_for_timeouts, self.timeout_check_interval)
  71. self.sockethandler.scan_for_timeouts()
  72. def bind(self, port, bind = '', reuse = False,
  73. ipv6_socket_style = 1, upnp = False):
  74. self.sockethandler.bind(port, bind, reuse, ipv6_socket_style, upnp)
  75. def find_and_bind(self, minport, maxport, bind = '', reuse = False,
  76. ipv6_socket_style = 1, upnp = 0, randomizer = False):
  77. return self.sockethandler.find_and_bind(minport, maxport, bind, reuse,
  78. ipv6_socket_style, upnp, randomizer)
  79. def start_connection_raw(self, dns, socktype, handler = None):
  80. return self.sockethandler.start_connection_raw(dns, socktype, handler)
  81. def start_connection(self, dns, handler = None, randomize = False):
  82. return self.sockethandler.start_connection(dns, handler, randomize)
  83. def get_stats(self):
  84. return self.sockethandler.get_stats()
  85. def pop_external(self):
  86. while self.externally_added:
  87. (a, b, c) = self.externally_added.pop(0)
  88. self._add_task(a, b, c)
  89. def listen_forever(self, handler):
  90. self.sockethandler.set_handler(handler)
  91. try:
  92. while not self.doneflag.isSet():
  93. try:
  94. self.pop_external()
  95. self._kill_tasks()
  96. if self.funcs:
  97. period = self.funcs[0][0] + 0.001 - clock()
  98. else:
  99. period = 2 ** 30
  100. if period < 0:
  101. period = 0
  102. events = self.sockethandler.do_poll(period)
  103. if self.doneflag.isSet():
  104. return
  105. while self.funcs and self.funcs[0][0] <= clock():
  106. garbage1, func, id = self.funcs.pop(0)
  107. if id in self.tasks_to_kill:
  108. pass
  109. try:
  110. # print func.func_name
  111. func()
  112. except (SystemError, MemoryError), e:
  113. self.failfunc(str(e))
  114. return
  115. except KeyboardInterrupt:
  116. # self.exception(True)
  117. return
  118. except:
  119. if self.noisy:
  120. self.exception()
  121. self.sockethandler.close_dead()
  122. self.sockethandler.handle_events(events)
  123. if self.doneflag.isSet():
  124. return
  125. self.sockethandler.close_dead()
  126. except (SystemError, MemoryError), e:
  127. self.failfunc(str(e))
  128. return
  129. except error:
  130. if self.doneflag.isSet():
  131. return
  132. except KeyboardInterrupt:
  133. # self.exception(True)
  134. return
  135. except:
  136. self.exception()
  137. if self.exccount > 10:
  138. return
  139. finally:
  140. # self.sockethandler.shutdown()
  141. self.finished.set()
  142. def is_finished(self):
  143. return self.finished.isSet()
  144. def wait_until_finished(self):
  145. self.finished.wait()
  146. def _kill_tasks(self):
  147. if self.tasks_to_kill:
  148. new_funcs = []
  149. for (t, func, id) in self.funcs:
  150. if id not in self.tasks_to_kill:
  151. new_funcs.append((t, func, id))
  152. self.funcs = new_funcs
  153. self.tasks_to_kill = []
  154. def kill_tasks(self, id):
  155. self.tasks_to_kill.append(id)
  156. def exception(self, kbint = False):
  157. if not kbint:
  158. self.excflag.set()
  159. self.exccount += 1
  160. if self.errorfunc is None:
  161. print_exc()
  162. else:
  163. data = StringIO()
  164. print_exc(file = data)
  165. # print data.getvalue() # report exception here too
  166. if not kbint: # don't report here if it's a keyboard interrupt
  167. self.errorfunc(data.getvalue())
  168. def shutdown(self):
  169. self.sockethandler.shutdown()