Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

interfaces.py 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. ###############################################################################
  2. #
  3. # The MIT License (MIT)
  4. #
  5. # Copyright (c) typedef int GmbH
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in
  15. # all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. # THE SOFTWARE.
  24. #
  25. ###############################################################################
  26. import abc
  27. from typing import Optional, Union, Tuple, Dict
  28. from autobahn.util import public
  29. from autobahn.websocket.types import ConnectionRequest, ConnectionResponse, ConnectingRequest
  30. from autobahn.wamp.types import TransportDetails
  31. __all__ = ('IWebSocketServerChannelFactory',
  32. 'IWebSocketClientChannelFactory',
  33. 'IWebSocketChannel',
  34. 'IWebSocketChannelFrameApi',
  35. 'IWebSocketChannelStreamingApi')
  36. class IWebSocketClientAgent(abc.ABC):
  37. """
  38. Instances implementing this interface create WebSocket
  39. connections.
  40. """
  41. def open(self, transport_config, options, protocol_class=None):
  42. """
  43. Open a new WebSocket connection.
  44. :param transport_config: the endpoint to connect to. A string
  45. containing a ws:// or wss:// URI (or a dict containing
  46. transport configuration?)
  47. :param options: any relevant options for this connection
  48. attempt. Can include: headers: a dict() of headers to send,
  49. anything currently in Factory / setProtocolOptions?
  50. :returns: a future which fires with a new WebSocketClientProtocol instance
  51. which has just completed the handshake, or an error.
  52. """
  53. @public
  54. class IWebSocketServerChannelFactory(abc.ABC):
  55. """
  56. WebSocket server protocol factories implement this interface, and create
  57. protocol instances which in turn implement
  58. """
  59. @abc.abstractmethod
  60. def __init__(self,
  61. url=None,
  62. protocols=None,
  63. server=None,
  64. headers=None,
  65. externalPort=None):
  66. """
  67. :param url: The WebSocket URL this factory is working for, e.g. ``ws://myhost.com/somepath``.
  68. For non-TCP transports like pipes or Unix domain sockets, provide ``None``.
  69. This will use an implicit URL of ``ws://localhost``.
  70. :type url: str
  71. :param protocols: List of subprotocols the server supports. The subprotocol used is the first from
  72. the list of subprotocols announced by the client that is contained in this list.
  73. :type protocols: list of str
  74. :param server: Server as announced in HTTP response header during opening handshake.
  75. :type server: str
  76. :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake.
  77. :type headers: dict
  78. :param externalPort: Optionally, the external visible port this server will be reachable under
  79. (i.e. when running behind a L2/L3 forwarding device).
  80. :type externalPort: int
  81. """
  82. @public
  83. @abc.abstractmethod
  84. def setSessionParameters(self,
  85. url=None,
  86. protocols=None,
  87. server=None,
  88. headers=None,
  89. externalPort=None):
  90. """
  91. Set WebSocket session parameters.
  92. :param url: The WebSocket URL this factory is working for, e.g. ``ws://myhost.com/somepath``.
  93. For non-TCP transports like pipes or Unix domain sockets, provide ``None``.
  94. This will use an implicit URL of ``ws://localhost``.
  95. :type url: str
  96. :param protocols: List of subprotocols the server supports. The subprotocol used is the first from the
  97. list of subprotocols announced by the client that is contained in this list.
  98. :type protocols: list of str
  99. :param server: Server as announced in HTTP response header during opening handshake.
  100. :type server: str
  101. :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake.
  102. :type headers: dict
  103. :param externalPort: Optionally, the external visible port this server will be reachable under
  104. (i.e. when running behind a L2/L3 forwarding device).
  105. :type externalPort: int
  106. """
  107. @public
  108. @abc.abstractmethod
  109. def setProtocolOptions(self,
  110. versions=None,
  111. webStatus=None,
  112. utf8validateIncoming=None,
  113. maskServerFrames=None,
  114. requireMaskedClientFrames=None,
  115. applyMask=None,
  116. maxFramePayloadSize=None,
  117. maxMessagePayloadSize=None,
  118. autoFragmentSize=None,
  119. failByDrop=None,
  120. echoCloseCodeReason=None,
  121. openHandshakeTimeout=None,
  122. closeHandshakeTimeout=None,
  123. tcpNoDelay=None,
  124. perMessageCompressionAccept=None,
  125. autoPingInterval=None,
  126. autoPingTimeout=None,
  127. autoPingSize=None,
  128. serveFlashSocketPolicy=None,
  129. flashSocketPolicy=None,
  130. allowedOrigins=None,
  131. allowNullOrigin=False,
  132. maxConnections=None,
  133. trustXForwardedFor=0):
  134. """
  135. Set WebSocket protocol options used as defaults for new protocol instances.
  136. :param versions: The WebSocket protocol versions accepted by the server
  137. (default: :func:`autobahn.websocket.protocol.WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS`).
  138. :type versions: list of ints or None
  139. :param webStatus: Return server status/version on HTTP/GET without WebSocket upgrade header (default: `True`).
  140. :type webStatus: bool or None
  141. :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: `True`).
  142. :type utf8validateIncoming: bool or None
  143. :param maskServerFrames: Mask server-to-client frames (default: `False`).
  144. :type maskServerFrames: bool or None
  145. :param requireMaskedClientFrames: Require client-to-server frames to be masked (default: `True`).
  146. :type requireMaskedClientFrames: bool or None
  147. :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and
  148. incoming frames (default: `True`).
  149. :type applyMask: bool or None
  150. :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or
  151. `0` for unlimited (default: `0`).
  152. :type maxFramePayloadSize: int or None
  153. :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that
  154. will be accepted when receiving or `0` for unlimited (default: `0`).
  155. :type maxMessagePayloadSize: int or None
  156. :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API)
  157. into frames with payload length `<=` this size or `0` for no auto-fragmentation (default: `0`).
  158. :type autoFragmentSize: int or None
  159. :param failByDrop: Fail connections by dropping the TCP connection without performing closing
  160. handshake (default: `True`).
  161. :type failByDrop: bool or None
  162. :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply
  163. with `code == 1000, reason = ""` (default: `False`).
  164. :type echoCloseCodeReason: bool or None
  165. :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or
  166. `0` to deactivate (default: `0`).
  167. :type openHandshakeTimeout: float or None
  168. :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout
  169. in seconds (default: `1`).
  170. :type closeHandshakeTimeout: float or None
  171. :param tcpNoDelay: TCP NODELAY ("Nagle") socket option (default: `True`).
  172. :type tcpNoDelay: bool or None
  173. :param perMessageCompressionAccept: Acceptor function for offers.
  174. :type perMessageCompressionAccept: callable or None
  175. :param autoPingInterval: Automatically send WebSocket pings every given seconds. When the peer does not respond
  176. in `autoPingTimeout`, drop the connection. Set to `0` to disable. (default: `0`).
  177. :type autoPingInterval: float or None
  178. :param autoPingTimeout: Wait this many seconds for the peer to respond to automatically sent pings. If the
  179. peer does not respond in time, drop the connection. Set to `0` to disable. (default: `0`).
  180. :type autoPingTimeout: float or None
  181. :param autoPingSize: Payload size for automatic pings/pongs. Must be an integer
  182. from `[12, 125]`. (default: `12`).
  183. :type autoPingSize: int or None
  184. :param serveFlashSocketPolicy: Serve the Flash Socket Policy when we receive a policy file request
  185. on this protocol. (default: `False`).
  186. :type serveFlashSocketPolicy: bool or None
  187. :param flashSocketPolicy: The flash socket policy to be served when we are serving
  188. the Flash Socket Policy on this protocol
  189. and when Flash tried to connect to the destination port. It must end with a null character.
  190. :type flashSocketPolicy: str or None
  191. :param allowedOrigins: A list of allowed WebSocket origins (with '*' as a wildcard character).
  192. :type allowedOrigins: list or None
  193. :param allowNullOrigin: if True, allow WebSocket connections whose `Origin:` is `"null"`.
  194. :type allowNullOrigin: bool
  195. :param maxConnections: Maximum number of concurrent connections. Set to `0` to disable (default: `0`).
  196. :type maxConnections: int or None
  197. :param trustXForwardedFor: Number of trusted web servers in front of this server that add their
  198. own X-Forwarded-For header (default: `0`)
  199. :type trustXForwardedFor: int
  200. """
  201. @public
  202. @abc.abstractmethod
  203. def resetProtocolOptions(self):
  204. """
  205. Reset all WebSocket protocol options to defaults.
  206. """
  207. @public
  208. class IWebSocketClientChannelFactory(abc.ABC):
  209. """
  210. WebSocket client protocol factories implement this interface, and create
  211. protocol instances which in turn implement
  212. """
  213. @abc.abstractmethod
  214. def __init__(self,
  215. url=None,
  216. origin=None,
  217. protocols=None,
  218. useragent=None,
  219. headers=None,
  220. proxy=None):
  221. """
  222. Note that you MUST provide URL either here or set using
  223. :meth:`autobahn.websocket.WebSocketClientFactory.setSessionParameters`
  224. *before* the factory is started.
  225. :param url: WebSocket URL this factory will connect to, e.g. ``ws://myhost.com/somepath?param1=23``.
  226. For non-TCP transports like pipes or Unix domain sockets, provide ``None``.
  227. This will use an implicit URL of ``ws://localhost``.
  228. :type url: str
  229. :param origin: The origin to be sent in WebSocket opening handshake or None (default: `None`).
  230. :type origin: str
  231. :param protocols: List of subprotocols the client should announce in WebSocket opening
  232. handshake (default: `[]`).
  233. :type protocols: list of strings
  234. :param useragent: User agent as announced in HTTP request header or None (default: `AutobahnWebSocket/?.?.?`).
  235. :type useragent: str
  236. :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake.
  237. :type headers: dict
  238. :param proxy: Explicit proxy server to use; a dict with ``host`` and ``port`` keys
  239. :type proxy: dict or None
  240. """
  241. @public
  242. @abc.abstractmethod
  243. def setSessionParameters(self,
  244. url=None,
  245. origin=None,
  246. protocols=None,
  247. useragent=None,
  248. headers=None,
  249. proxy=None):
  250. """
  251. Set WebSocket session parameters.
  252. :param url: WebSocket URL this factory will connect to, e.g. `ws://myhost.com/somepath?param1=23`.
  253. For non-TCP transports like pipes or Unix domain sockets, provide `None`.
  254. This will use an implicit URL of `ws://localhost`.
  255. :type url: str
  256. :param origin: The origin to be sent in opening handshake.
  257. :type origin: str
  258. :param protocols: List of WebSocket subprotocols the client should announce in opening handshake.
  259. :type protocols: list of strings
  260. :param useragent: User agent as announced in HTTP request header during opening handshake.
  261. :type useragent: str
  262. :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake.
  263. :type headers: dict
  264. :param proxy: (Optional) a dict with ``host`` and ``port`` keys specifying a proxy to use
  265. :type proxy: dict or None
  266. """
  267. @public
  268. @abc.abstractmethod
  269. def setProtocolOptions(self,
  270. version=None,
  271. utf8validateIncoming=None,
  272. acceptMaskedServerFrames=None,
  273. maskClientFrames=None,
  274. applyMask=None,
  275. maxFramePayloadSize=None,
  276. maxMessagePayloadSize=None,
  277. autoFragmentSize=None,
  278. failByDrop=None,
  279. echoCloseCodeReason=None,
  280. serverConnectionDropTimeout=None,
  281. openHandshakeTimeout=None,
  282. closeHandshakeTimeout=None,
  283. tcpNoDelay=None,
  284. perMessageCompressionOffers=None,
  285. perMessageCompressionAccept=None,
  286. autoPingInterval=None,
  287. autoPingTimeout=None,
  288. autoPingSize=None):
  289. """
  290. Set WebSocket protocol options used as defaults for _new_ protocol instances.
  291. :param version: The WebSocket protocol spec (draft) version to be used
  292. (default: :func:`autobahn.websocket.protocol.WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS`).
  293. :type version: int
  294. :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: `True`).
  295. :type utf8validateIncoming: bool
  296. :param acceptMaskedServerFrames: Accept masked server-to-client frames (default: `False`).
  297. :type acceptMaskedServerFrames: bool
  298. :param maskClientFrames: Mask client-to-server frames (default: `True`).
  299. :type maskClientFrames: bool
  300. :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and
  301. incoming frames (default: `True`).
  302. :type applyMask: bool
  303. :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or
  304. `0` for unlimited (default: `0`).
  305. :type maxFramePayloadSize: int
  306. :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that
  307. will be accepted when receiving or `0` for unlimited (default: `0`).
  308. :type maxMessagePayloadSize: int
  309. :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API)
  310. into frames with payload length `<=` this size or `0` for no auto-fragmentation (default: `0`).
  311. :type autoFragmentSize: int
  312. :param failByDrop: Fail connections by dropping the TCP connection without performing
  313. closing handshake (default: `True`).
  314. :type failByDrop: bool
  315. :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply
  316. with `code == 1000, reason = ""` (default: `False`).
  317. :type echoCloseCodeReason: bool
  318. :param serverConnectionDropTimeout: When the client expects the server to drop the TCP, timeout in
  319. seconds (default: `1`).
  320. :type serverConnectionDropTimeout: float
  321. :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or `0` to
  322. deactivate (default: `0`).
  323. :type openHandshakeTimeout: float
  324. :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout
  325. in seconds (default: `1`).
  326. :type closeHandshakeTimeout: float
  327. :param tcpNoDelay: TCP NODELAY ("Nagle"): bool socket option (default: `True`).
  328. :type tcpNoDelay: bool
  329. :param perMessageCompressionOffers: A list of offers to provide to the server for the permessage-compress
  330. WebSocket extension. Must be a list of instances of subclass of PerMessageCompressOffer.
  331. :type perMessageCompressionOffers: list of instance of subclass of PerMessageCompressOffer
  332. :param perMessageCompressionAccept: Acceptor function for responses.
  333. :type perMessageCompressionAccept: callable
  334. :param autoPingInterval: Automatically send WebSocket pings every given seconds. When the peer does not respond
  335. in `autoPingTimeout`, drop the connection. Set to `0` to disable. (default: `0`).
  336. :type autoPingInterval: float or None
  337. :param autoPingTimeout: Wait this many seconds for the peer to respond to automatically sent pings. If the
  338. peer does not respond in time, drop the connection. Set to `0` to disable. (default: `0`).
  339. :type autoPingTimeout: float or None
  340. :param autoPingSize: Payload size for automatic pings/pongs. Must be an integer
  341. from `[12, 125]`. (default: `12`).
  342. :type autoPingSize: int
  343. """
  344. @public
  345. @abc.abstractmethod
  346. def resetProtocolOptions(self):
  347. """
  348. Reset all WebSocket protocol options to defaults.
  349. """
  350. @public
  351. class IWebSocketChannel(abc.ABC):
  352. """
  353. A WebSocket channel is a bidirectional, full-duplex, ordered, reliable message channel
  354. over a WebSocket connection as specified in RFC6455.
  355. This interface defines a message-based API to WebSocket plus auxiliary hooks
  356. and methods.
  357. When a WebSocket connection is established, the following callbacks are fired:
  358. * :meth:`IWebSocketChannel.onConnecting`: Transport bytestream open
  359. * :meth:`IWebSocketChannel.onConnect`: WebSocket handshake
  360. * :meth:`IWebSocketChannel.onOpen`: WebSocket connection open
  361. Once a WebSocket connection is open, messages can be sent and received using:
  362. * :meth:`IWebSocketChannel.sendMessage`
  363. * :meth:`IWebSocketChannel.onMessage`
  364. The WebSocket connection can be closed and closing observed using:
  365. * :meth:`IWebSocketChannel.sendClose`
  366. * :meth:`IWebSocketChannel.onClose`
  367. Finally, WebSocket ping/pong messages
  368. * :meth:`IWebSocketChannel.sendPing`
  369. * :meth:`IWebSocketChannel.onPing`
  370. * :meth:`IWebSocketChannel.sendPong`
  371. * :meth:`IWebSocketChannel.onPong`
  372. which are used for e.g. for heart-beating.
  373. """
  374. @public
  375. @abc.abstractmethod
  376. def onConnecting(self, transport_details: TransportDetails) -> Optional[ConnectingRequest]:
  377. """
  378. This method is called when the WebSocket peer is connected at the byte stream level (e.g. TCP,
  379. TLS or Serial), but before the WebSocket opening handshake (e.g. at the HTTP request level).
  380. :param transport_details: information about the transport.
  381. :returns: A :class:`autobahn.websocket.types.ConnectingRequest`
  382. instance is returned to indicate which options should be
  383. used for this connection. If you wish to use the default
  384. behavior, ``None`` may be returned (this is the default).
  385. """
  386. @public
  387. @abc.abstractmethod
  388. def onConnect(self, request_or_response: Union[ConnectionRequest, ConnectionResponse]) -> \
  389. Union[Optional[str], Tuple[Optional[str], Dict[str, str]]]:
  390. """
  391. Callback fired during WebSocket opening handshake when a client connects to a server with
  392. request with a :class:`ConnectionRequest` from the client or when a server connection was established
  393. by a client with a :class:`ConnectionResponse` response from the server.
  394. *This method may run asynchronously.*
  395. :param request_or_response: Connection request (for servers) or response (for clients).
  396. :type request_or_response: Instance of :class:`autobahn.websocket.types.ConnectionRequest`
  397. or :class:`autobahn.websocket.types.ConnectionResponse`.
  398. :returns: When this callback is fired on a WebSocket **server**, you may return one of:
  399. ``None``: the connection is accepted with no specific WebSocket subprotocol,
  400. ``str``: the connection is accepted with the returned name as the WebSocket subprotocol, or
  401. ``(str, dict)``: a pair of subprotocol accepted and HTTP headers to send to the client.
  402. When this callback is fired on a WebSocket **client**, this method must return ``None``.
  403. To deny a connection (client and server), raise an Exception.
  404. You can also return a Deferred/Future that resolves/rejects to the above.
  405. """
  406. @public
  407. @abc.abstractmethod
  408. def onOpen(self):
  409. """
  410. Callback fired when the initial WebSocket opening handshake was completed.
  411. You now can send and receive WebSocket messages.
  412. *This method may run asynchronously.*
  413. """
  414. @public
  415. @abc.abstractmethod
  416. def sendMessage(self, payload: bytes, isBinary: bool):
  417. """
  418. Send a WebSocket message over the connection to the peer.
  419. :param payload: The WebSocket message to be sent.
  420. :param isBinary: Flag indicating whether payload is binary or UTF-8 encoded text.
  421. """
  422. @public
  423. @abc.abstractmethod
  424. def onMessage(self, payload: bytes, isBinary: bool):
  425. """
  426. Callback fired when a complete WebSocket message was received.
  427. *This method may run asynchronously.*
  428. :param payload: The WebSocket message received.
  429. :param isBinary: Flag indicating whether payload is binary or UTF-8 encoded text.
  430. """
  431. @public
  432. @abc.abstractmethod
  433. def sendClose(self, code: Optional[int] = None, reason: Optional[str] = None):
  434. """
  435. Starts a WebSocket closing handshake tearing down the WebSocket connection.
  436. :param code: An optional close status code (``1000`` for normal close or ``3000-4999`` for
  437. application specific close).
  438. :param reason: An optional close reason (a string that when present, a status
  439. code MUST also be present).
  440. """
  441. @public
  442. @abc.abstractmethod
  443. def onClose(self, wasClean: bool, code: int, reason: str):
  444. """
  445. Callback fired when the WebSocket connection has been closed (WebSocket closing
  446. handshake has been finished or the connection was closed uncleanly).
  447. :param wasClean: ``True`` iff the WebSocket connection was closed cleanly.
  448. :param code: Close status code as sent by the WebSocket peer.
  449. :param reason: Close reason as sent by the WebSocket peer.
  450. """
  451. @abc.abstractmethod
  452. def sendPing(self, payload: Optional[bytes] = None):
  453. """
  454. Send a WebSocket ping to the peer.
  455. A peer is expected to pong back the payload a soon as "practical". When more than
  456. one ping is outstanding at a peer, the peer may elect to respond only to the last ping.
  457. :param payload: An (optional) arbitrary payload of length **less than 126** octets.
  458. """
  459. @abc.abstractmethod
  460. def onPing(self, payload: bytes):
  461. """
  462. Callback fired when a WebSocket ping was received. A default implementation responds
  463. by sending a WebSocket pong.
  464. :param payload: Payload of ping (when there was any). Can be arbitrary, up to `125` octets.
  465. """
  466. @abc.abstractmethod
  467. def sendPong(self, payload: Optional[bytes] = None):
  468. """
  469. Send a WebSocket pong to the peer.
  470. A WebSocket pong may be sent unsolicited. This serves as a unidirectional heartbeat.
  471. A response to an unsolicited pong is "not expected".
  472. :param payload: An (optional) arbitrary payload of length < 126 octets.
  473. """
  474. @abc.abstractmethod
  475. def onPong(self, payload: bytes):
  476. """
  477. Callback fired when a WebSocket pong was received. A default implementation does nothing.
  478. :param payload: Payload of pong (when there was any). Can be arbitrary, up to 125 octets.
  479. """
  480. class IWebSocketChannelFrameApi(IWebSocketChannel):
  481. """
  482. Frame-based API to a WebSocket channel.
  483. """
  484. @abc.abstractmethod
  485. def onMessageBegin(self, isBinary: bool):
  486. """
  487. Callback fired when receiving of a new WebSocket message has begun.
  488. :param isBinary: ``True`` if payload is binary, else the payload is UTF-8 encoded text.
  489. :type isBinary: bool
  490. """
  491. @abc.abstractmethod
  492. def onMessageFrame(self, payload: bytes):
  493. """
  494. Callback fired when a complete WebSocket message frame for a previously begun
  495. WebSocket message has been received.
  496. :param payload: Message frame payload (a list of chunks received).
  497. :type payload: list of bytes
  498. """
  499. @abc.abstractmethod
  500. def onMessageEnd(self):
  501. """
  502. Callback fired when a WebSocket message has been completely received (the last
  503. WebSocket frame for that message has been received).
  504. """
  505. @abc.abstractmethod
  506. def beginMessage(self, isBinary: bool = False, doNotCompress: bool = False):
  507. """
  508. Begin sending a new WebSocket message.
  509. :param isBinary: ``True`` if payload is binary, else the payload must be UTF-8 encoded text.
  510. :type isBinary: bool
  511. :param doNotCompress: If ``True``, never compress this message. This only applies to
  512. Hybi-Mode and only when WebSocket compression has been negotiated on the WebSocket
  513. connection. Use when you know the payload incompressible (e.g. encrypted or
  514. already compressed).
  515. :type doNotCompress: bool
  516. """
  517. @abc.abstractmethod
  518. def sendMessageFrame(self, payload: bytes, sync: bool = False):
  519. """
  520. When a message has been previously begun, send a complete message frame in one go.
  521. :param payload: The message frame payload. When sending a text message, the payload must
  522. be UTF-8 encoded already.
  523. :type payload: bytes
  524. :param sync: If ``True``, try to force data onto the wire immediately.S
  525. .. warning:: Do NOT use this feature for normal applications. Performance likely will suffer significantly. This feature is mainly here for use by Autobahn|Testsuite.
  526. :type sync: bool
  527. """
  528. @abc.abstractmethod
  529. def endMessage(self):
  530. """
  531. End a message previously begun message. No more frames may be sent (for that message).
  532. You have to begin a new message before sending again.
  533. """
  534. class IWebSocketChannelStreamingApi(IWebSocketChannelFrameApi):
  535. """
  536. Streaming API to a WebSocket channel.
  537. """
  538. @abc.abstractmethod
  539. def onMessageFrameBegin(self, length: int):
  540. """
  541. Callback fired when receiving a new message frame has begun.
  542. A default implementation will prepare to buffer message frame data.
  543. :param length: Payload length of message frame which is subsequently received.
  544. :type length: int
  545. """
  546. @abc.abstractmethod
  547. def onMessageFrameData(self, payload: bytes):
  548. """
  549. Callback fired when receiving data within a previously begun message frame.
  550. A default implementation will buffer data for frame.
  551. :param payload: Partial payload for message frame.
  552. :type payload: bytes
  553. """
  554. @abc.abstractmethod
  555. def onMessageFrameEnd(self):
  556. """
  557. Callback fired when a previously begun message frame has been completely received.
  558. A default implementation will flatten the buffered frame data and
  559. fire `onMessageFrame`.
  560. """
  561. @abc.abstractmethod
  562. def beginMessageFrame(self, length: int):
  563. """
  564. Begin sending a new message frame.
  565. :param length: Length of the frame which is to be started. Must be less or equal **2^63**.
  566. :type length: int
  567. """
  568. @abc.abstractmethod
  569. def sendMessageFrameData(self, payload: bytes, sync: bool = False):
  570. """
  571. Send out data when within a message frame (message was begun, frame was begun).
  572. Note that the frame is automatically ended when enough data has been sent.
  573. In other words, there is no ``endMessageFrame``, since you have begun the frame
  574. specifying the frame length, which implicitly defined the frame end. This is different
  575. from messages, which you begin *and* end explicitly , since a message can contain
  576. an unlimited number of frames.
  577. :param payload: Frame payload to send.
  578. :type payload: bytes
  579. :param sync: If ``True``, try to force data onto the wire immediately.
  580. .. warning:: Do NOT use this feature for normal applications. Performance likely will suffer significantly. This feature is mainly here for use by Autobahn|Testsuite.
  581. :type sync: bool
  582. :returns: When the currently sent message frame is still incomplete, returns octets
  583. remaining to be sent. When the frame is complete, returns **0**. Otherwise the amount
  584. of unconsumed data in payload argument is returned.
  585. :rtype: int
  586. """