Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

229 wiersze
7.1 KiB

  1. cdef __tcp_init_uv_handle(UVStream handle, Loop loop, unsigned int flags):
  2. cdef int err
  3. handle._handle = <uv.uv_handle_t*>PyMem_RawMalloc(sizeof(uv.uv_tcp_t))
  4. if handle._handle is NULL:
  5. handle._abort_init()
  6. raise MemoryError()
  7. err = uv.uv_tcp_init_ex(handle._loop.uvloop,
  8. <uv.uv_tcp_t*>handle._handle,
  9. flags)
  10. if err < 0:
  11. handle._abort_init()
  12. raise convert_error(err)
  13. handle._finish_init()
  14. cdef __tcp_bind(UVStream handle, system.sockaddr* addr, unsigned int flags):
  15. cdef int err
  16. err = uv.uv_tcp_bind(<uv.uv_tcp_t *>handle._handle,
  17. addr, flags)
  18. if err < 0:
  19. exc = convert_error(err)
  20. raise exc
  21. cdef __tcp_open(UVStream handle, int sockfd):
  22. cdef int err
  23. err = uv.uv_tcp_open(<uv.uv_tcp_t *>handle._handle,
  24. <uv.uv_os_sock_t>sockfd)
  25. if err < 0:
  26. exc = convert_error(err)
  27. raise exc
  28. cdef __tcp_get_socket(UVSocketHandle handle):
  29. cdef:
  30. int buf_len = sizeof(system.sockaddr_storage)
  31. int fileno
  32. int err
  33. system.sockaddr_storage buf
  34. fileno = handle._fileno()
  35. err = uv.uv_tcp_getsockname(<uv.uv_tcp_t*>handle._handle,
  36. <system.sockaddr*>&buf,
  37. &buf_len)
  38. if err < 0:
  39. raise convert_error(err)
  40. return PseudoSocket(buf.ss_family, uv.SOCK_STREAM, 0, fileno)
  41. @cython.no_gc_clear
  42. cdef class TCPServer(UVStreamServer):
  43. @staticmethod
  44. cdef TCPServer new(Loop loop, object protocol_factory, Server server,
  45. unsigned int flags,
  46. object backlog,
  47. object ssl,
  48. object ssl_handshake_timeout,
  49. object ssl_shutdown_timeout):
  50. cdef TCPServer handle
  51. handle = TCPServer.__new__(TCPServer)
  52. handle._init(loop, protocol_factory, server, backlog,
  53. ssl, ssl_handshake_timeout, ssl_shutdown_timeout)
  54. __tcp_init_uv_handle(<UVStream>handle, loop, flags)
  55. return handle
  56. cdef _new_socket(self):
  57. return __tcp_get_socket(<UVSocketHandle>self)
  58. cdef _open(self, int sockfd):
  59. self._ensure_alive()
  60. try:
  61. __tcp_open(<UVStream>self, sockfd)
  62. except Exception as exc:
  63. self._fatal_error(exc, True)
  64. else:
  65. self._mark_as_open()
  66. cdef bind(self, system.sockaddr* addr, unsigned int flags=0):
  67. self._ensure_alive()
  68. try:
  69. __tcp_bind(<UVStream>self, addr, flags)
  70. except Exception as exc:
  71. self._fatal_error(exc, True)
  72. else:
  73. self._mark_as_open()
  74. cdef UVStream _make_new_transport(self, object protocol, object waiter,
  75. object context):
  76. cdef TCPTransport tr
  77. tr = TCPTransport.new(self._loop, protocol, self._server, waiter,
  78. context)
  79. return <UVStream>tr
  80. @cython.no_gc_clear
  81. cdef class TCPTransport(UVStream):
  82. @staticmethod
  83. cdef TCPTransport new(Loop loop, object protocol, Server server,
  84. object waiter, object context):
  85. cdef TCPTransport handle
  86. handle = TCPTransport.__new__(TCPTransport)
  87. handle._init(loop, protocol, server, waiter, context)
  88. __tcp_init_uv_handle(<UVStream>handle, loop, uv.AF_UNSPEC)
  89. handle.__peername_set = 0
  90. handle.__sockname_set = 0
  91. handle._set_nodelay()
  92. return handle
  93. cdef _set_nodelay(self):
  94. cdef int err
  95. self._ensure_alive()
  96. err = uv.uv_tcp_nodelay(<uv.uv_tcp_t*>self._handle, 1)
  97. if err < 0:
  98. raise convert_error(err)
  99. cdef _call_connection_made(self):
  100. # asyncio saves peername & sockname when transports are instantiated,
  101. # so that they're accessible even after the transport is closed.
  102. # We are doing the same thing here, except that we create Python
  103. # objects lazily, on request in get_extra_info()
  104. cdef:
  105. int err
  106. int buf_len
  107. buf_len = sizeof(system.sockaddr_storage)
  108. err = uv.uv_tcp_getsockname(<uv.uv_tcp_t*>self._handle,
  109. <system.sockaddr*>&self.__sockname,
  110. &buf_len)
  111. if err >= 0:
  112. # Ignore errors, this is an optional thing.
  113. # If something serious is going on, the transport
  114. # will crash later (in roughly the same way how
  115. # an asyncio transport would.)
  116. self.__sockname_set = 1
  117. buf_len = sizeof(system.sockaddr_storage)
  118. err = uv.uv_tcp_getpeername(<uv.uv_tcp_t*>self._handle,
  119. <system.sockaddr*>&self.__peername,
  120. &buf_len)
  121. if err >= 0:
  122. # Same as few lines above -- we don't really care
  123. # about error case here.
  124. self.__peername_set = 1
  125. UVBaseTransport._call_connection_made(self)
  126. def get_extra_info(self, name, default=None):
  127. if name == 'sockname':
  128. if self.__sockname_set:
  129. return __convert_sockaddr_to_pyaddr(
  130. <system.sockaddr*>&self.__sockname)
  131. elif name == 'peername':
  132. if self.__peername_set:
  133. return __convert_sockaddr_to_pyaddr(
  134. <system.sockaddr*>&self.__peername)
  135. return super().get_extra_info(name, default)
  136. cdef _new_socket(self):
  137. return __tcp_get_socket(<UVSocketHandle>self)
  138. cdef bind(self, system.sockaddr* addr, unsigned int flags=0):
  139. self._ensure_alive()
  140. __tcp_bind(<UVStream>self, addr, flags)
  141. cdef _open(self, int sockfd):
  142. self._ensure_alive()
  143. __tcp_open(<UVStream>self, sockfd)
  144. cdef connect(self, system.sockaddr* addr):
  145. cdef _TCPConnectRequest req
  146. req = _TCPConnectRequest(self._loop, self)
  147. req.connect(addr)
  148. cdef class _TCPConnectRequest(UVRequest):
  149. cdef:
  150. TCPTransport transport
  151. uv.uv_connect_t _req_data
  152. def __cinit__(self, loop, transport):
  153. self.request = <uv.uv_req_t*>&self._req_data
  154. self.request.data = <void*>self
  155. self.transport = transport
  156. cdef connect(self, system.sockaddr* addr):
  157. cdef int err
  158. err = uv.uv_tcp_connect(<uv.uv_connect_t*>self.request,
  159. <uv.uv_tcp_t*>self.transport._handle,
  160. addr,
  161. __tcp_connect_callback)
  162. if err < 0:
  163. exc = convert_error(err)
  164. self.on_done()
  165. raise exc
  166. cdef void __tcp_connect_callback(
  167. uv.uv_connect_t* req,
  168. int status,
  169. ) noexcept with gil:
  170. cdef:
  171. _TCPConnectRequest wrapper
  172. TCPTransport transport
  173. wrapper = <_TCPConnectRequest> req.data
  174. transport = wrapper.transport
  175. if status < 0:
  176. exc = convert_error(status)
  177. else:
  178. exc = None
  179. try:
  180. transport._on_connect(exc)
  181. except BaseException as ex:
  182. wrapper.transport._fatal_error(ex, False)
  183. finally:
  184. wrapper.on_done()