diff --git a/README.md b/README.md index 74b43564..f8abff32 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,14 @@ For complete API documentation, please consult the [reference documentation](htt For more information, including some tutorials, please visit the project's [homepage](http://autobahn.ws/python). +## Performance + +**Autobahn**|Python is portable, well tuned code. You can further accelerate performance by + +* Running under [PyPy](http://pypy.org/) or +* on CPython, install the native accelerators [wsaccel](https://pypi.python.org/pypi/wsaccel/) and [ujson](https://pypi.python.org/pypi/ujson/) + + ## Get in touch Get in touch on IRC `#autobahn` on `chat.freenode.net`, follow us on [Twitter](https://twitter.com/autobahnws) or join the [mailing list](http://groups.google.com/group/autobahnws). diff --git a/autobahn/autobahn/interfaces.py b/autobahn/autobahn/interfaces.py index 26342273..095f430d 100644 --- a/autobahn/autobahn/interfaces.py +++ b/autobahn/autobahn/interfaces.py @@ -23,7 +23,7 @@ from zope.interface import Interface, Attribute class IWebSocketChannel(Interface): """ - A WebSocket channel is a bidirectional, ordered, reliable message channel + A WebSocket channel is a bidirectional, full-duplex, ordered, reliable message channel over a WebSocket connection as specified in RFC6455. This interface defines a message-based API to WebSocket plus auxiliary hooks @@ -32,8 +32,9 @@ class IWebSocketChannel(Interface): def onConnect(requestOrResponse): """ - Callback fired when a client connects (with request from client) or when - server connection established (with response from server). + Callback fired during WebSocket opening handshake when a client connects (with + request from client) or when server connection established (with response from + server). :param requestOrResponse: Connection request or response. :type requestOrResponse: Instance of :class:`autobahn.websocket.protocol.ConnectionRequest` @@ -43,6 +44,7 @@ class IWebSocketChannel(Interface): def onOpen(): """ Callback fired when the initial WebSocket opening handshake was completed. + You now can send and receive WebSocket messages. """ def sendMessage(payload, isBinary = False, fragmentSize = None, sync = False, doNotCompress = False): @@ -51,22 +53,22 @@ class IWebSocketChannel(Interface): You can send text or binary messages, and optionally specifiy a payload fragment size. When the latter is given, the payload will be split up into WebSocket frames each with - payload <= the `fragmentSize` given. + payload length `<= fragmentSize`. :param payload: The message payload. :type payload: bytes :param isBinary: `True` iff payload is binary, else the payload must be UTF-8 encoded text. - :type bool + :type isBinary: bool :param fragmentSize: Fragment message into WebSocket fragments of this size. :type fragmentSize: int :param sync: Iff `True`, try to force data onto the wire immediately. Note: do NOT use - this normally, performance likely will suffer significantly. This feature - is mainly here for use by the testsuite. + this normally unless you know what you are doing. Performance likely will + suffer significantly. This feature is mainly here for use by Autobahn|Testsuite. :type sync: bool :param doNotCompress: Iff `True`, never compress this message. This only applies to - Hybi-Mode and when WebSocket compression has been negotiated on - the WebSocket client-server connection. Use when you know the - payload is not compressible (e.g. encrypted or already compressed). + Hybi-Mode and only when WebSocket compression has been negotiated on + the WebSocket connection. Use when you know the payload + uncompressible (e.g. encrypted or already compressed). :type doNotCompress: bool """ @@ -85,8 +87,8 @@ class IWebSocketChannel(Interface): """ Starts a WebSocket closing handshake tearing down the WebSocket connection. - :param code: An optional close status code (1000 for normal close or 3000-4999 for - application specific close).. + :param code: An optional close status code (`1000` for normal close or `3000-4999` for + application specific close). :type code: int :param reason: An optional close reason (a string that when present, a status code MUST also be present). @@ -106,6 +108,14 @@ class IWebSocketChannel(Interface): :type reason: str """ + def sendPreparedMessage(preparedMsg): + """ + Send a message that was previously prepared with :func:`autobahn.websocket.protocol.WebSocketFactory.prepareMessage`. + + :param prepareMessage: A previsouly prepared message. + :type prepareMessage: Instance of :class:`autobahn.websocket.protocol.PreparedMessage`. + """ + def sendPing(payload = None): """ Send a WebSocket ping to the peer. @@ -113,7 +123,7 @@ class IWebSocketChannel(Interface): A peer is expected to pong back the payload a soon as "practical". When more than one ping is outstanding at a peer, the peer may elect to respond only to the last ping. - :param payload: An (optional) arbitrary payload of length < 126 octets. + :param payload: An (optional) arbitrary payload of length `<126` octets. :type payload: bytes """ @@ -122,7 +132,7 @@ class IWebSocketChannel(Interface): Callback fired when a WebSocket ping was received. A default implementation responds by sending a WebSocket pong. - :param payload: Payload of ping (when there was any). Can be arbitrary, up to 125 octets. + :param payload: Payload of ping (when there was any). Can be arbitrary, up to `125` octets. :type payload: bytes """ @@ -137,7 +147,7 @@ class IWebSocketChannel(Interface): :type payload: bytes """ - def onPong(self, payload): + def onPong(payload): """ Callback fired when a WebSocket pong was received. A default implementation does nothing. @@ -181,9 +191,9 @@ class IWebSocketChannelFrameApi(IWebSocketChannel): :param isBinary: `True` iff payload is binary, else the payload must be UTF-8 encoded text. :type isBinary: bool :param doNotCompress: Iff `True`, never compress this message. This only applies to - Hybi-Mode and when WebSocket compression has been negotiated on - the WebSocket client-server connection. Use when you know the - payload is not compressible (e.g. encrypted or already compressed). + Hybi-Mode and only when WebSocket compression has been negotiated on + the WebSocket connection. Use when you know the payload + uncompressible (e.g. encrypted or already compressed). :type doNotCompress: bool """ @@ -195,12 +205,12 @@ class IWebSocketChannelFrameApi(IWebSocketChannel): be UTF-8 encoded already. :type payload: bytes :param sync: Iff `True`, try to force data onto the wire immediately. Note: do NOT use - this normally, performance likely will suffer significantly. This feature - is mainly here for use by the testsuite. + this normally unless you know what you are doing. Performance likely will + suffer significantly. This feature is mainly here for use by Autobahn|Testsuite. :type sync: bool """ - def endMessage(self): + def endMessage(): """ End a message previously begun message. No more frames may be sent (for that message). You have to begin a new message before sending again. @@ -213,7 +223,7 @@ class IWebSocketChannelStreamingApi(IWebSocketChannelFrameApi): Streaming API to a WebSocket channel. """ - def onMessageFrameBegin(self, length): + def onMessageFrameBegin(length): """ Callback fired when receiving a new message frame has begun. A default implementation will prepare to buffer message frame data. @@ -222,48 +232,49 @@ class IWebSocketChannelStreamingApi(IWebSocketChannelFrameApi): :type length: int """ - def onMessageFrameData(self, payload): + def onMessageFrameData(payload): """ Callback fired when receiving data within a previously begun message frame. A default implementation will buffer data for frame. :param payload: Partial payload for message frame. - :type payload: str + :type payload: bytes """ - def onMessageFrameEnd(self): + def onMessageFrameEnd(): """ Callback fired when a previously begun message frame has been completely received. A default implementation will flatten the buffered frame data and fire `onMessageFrame`. """ - def beginMessageFrame(self, length): + def beginMessageFrame(length): """ Begin sending a new message frame. - :param length: Length of the frame which is to be started. Must be >= 0 and <= 2^63. + :param length: Length of the frame which is to be started. Must be `>= 0` and `<= 2^63`. :type length: int """ - def sendMessageFrameData(self, payload, sync = False): + def sendMessageFrameData(payload, sync = False): """ Send out data when within a message frame (message was begun, frame was begun). Note that the frame is automatically ended when enough data has been sent. In other words, there is no `endMessageFrame`, since you have begun the frame specifying the frame length, which implicitly defined the frame end. This is different - from messages, which you begin and end, since a message can contain an unlimited number - of frames. + from messages, which you begin *and* end explicitly , since a message can contain + an unlimited number of frames. - :param payload: bytes + :param payload: Frame payload to send. + :type payload: bytes :param sync: Iff `True`, try to force data onto the wire immediately. Note: do NOT use - this normally, performance likely will suffer significantly. This feature - is mainly here for use by the testsuite. + this normally unless you know what you are doing. Performance likely will + suffer significantly. This feature is mainly here for use by Autobahn|Testsuite. :type sync: bool :returns: int -- When the currently sent message frame is still incomplete, returns octets remaining to be sent. When the frame is complete, - returns <= 0, when < 0, the amount of unconsumed data in payload + returns `0`, when `< 0`, the amount of unconsumed data in payload argument. """ diff --git a/autobahn/autobahn/twisted/choosereactor.py b/autobahn/autobahn/twisted/choosereactor.py index 3e625a3b..19123f64 100644 --- a/autobahn/autobahn/twisted/choosereactor.py +++ b/autobahn/autobahn/twisted/choosereactor.py @@ -77,21 +77,26 @@ def install_optimal_reactor(): -def install_reactor(_reactor = None, verbose = False): +def install_reactor(explicitReactor = None, verbose = False): """ - Install Twisted reactor. This is used from CLI. + Install Twisted reactor. + + :param explicitReactor: If provided, install this reactor. Else, install optimal reactor. + :type explicitReactor: obj + :param verbose: If `True`, print what happens. + :type verbose: bool """ import sys - if _reactor: + if explicitReactor: ## install explicitly given reactor ## from twisted.application.reactors import installReactor - print("Trying to install explicitly specified Twisted reactor '%s'" % _reactor) + print("Trying to install explicitly specified Twisted reactor '%s'" % explicitReactor) try: - installReactor(_reactor) + installReactor(explicitReactor) except Exception as e: - print("Could not install Twisted reactor %s%s" % (_reactor, ' ["%s"]' % e if verbose else '')) + print("Could not install Twisted reactor %s%s" % (explicitReactor, ' ["%s"]' % e if verbose else '')) sys.exit(1) else: ## automatically choose optimal reactor diff --git a/autobahn/autobahn/twisted/flashpolicy.py b/autobahn/autobahn/twisted/flashpolicy.py index 4db214c0..b6883e1d 100644 --- a/autobahn/autobahn/twisted/flashpolicy.py +++ b/autobahn/autobahn/twisted/flashpolicy.py @@ -35,7 +35,7 @@ class FlashPolicyProtocol(Protocol): older browser, in particular MSIE9/8. See: - * `Autobahn WebSocket fallbacks example `_ + * `Autobahn WebSocket fallbacks example `_ * `Flash policy files background `_ """ @@ -96,6 +96,8 @@ class FlashPolicyFactory(Factory): :param allowedPort: The port to which Flash player should be allowed to connect. :type allowedPort: int + :param reactor: Twisted reactor to use. If not given, autoimport. + :type reactor: obj """ ## lazy import to avoid reactor install upon module import if reactor is None: diff --git a/autobahn/autobahn/websocket/http.py b/autobahn/autobahn/websocket/http.py index 7125ec4a..f3987f3b 100644 --- a/autobahn/autobahn/websocket/http.py +++ b/autobahn/autobahn/websocket/http.py @@ -217,7 +217,7 @@ NETWORK_CONNECT_TIMEOUT = (599, "Network connect timeout error (Informal conven class HttpException(Exception): """ Throw an instance of this class to deny a WebSocket connection - during handshake in :meth:`autobahn.websocket.WebSocketServerProtocol.onConnect`. + during handshake in :meth:`autobahn.websocket.protocol.WebSocketServerProtocol.onConnect`. """ def __init__(self, code, reason): diff --git a/autobahn/autobahn/websocket/protocol.py b/autobahn/autobahn/websocket/protocol.py index d9cdd951..9fad4ee5 100644 --- a/autobahn/autobahn/websocket/protocol.py +++ b/autobahn/autobahn/websocket/protocol.py @@ -273,9 +273,9 @@ class FrameHeader: class ConnectionRequest: """ - Thin-wrapper for WebSocket connection request information - provided in :meth:`autobahn.websocket.WebSocketServerProtocol.onConnect` when a WebSocket - client establishes a connection to a WebSocket server. + Thin-wrapper for WebSocket connection request information provided in + :meth:`autobahn.websocket.protocol.WebSocketServerProtocol.onConnect` when + a WebSocket client want to establish a connection to a WebSocket server. """ def __init__(self, peer, headers, host, path, params, version, origin, protocols, extensions): """ @@ -330,9 +330,9 @@ class ConnectionRequest: class ConnectionResponse: """ - Thin-wrapper for WebSocket connection response information - provided in :meth:`autobahn.websocket.WebSocketClientProtocol.onConnect` when a WebSocket - client has established a connection to a WebSocket server. + Thin-wrapper for WebSocket connection response information provided in + :meth:`autobahn.websocket.protocol.WebSocketClientProtocol.onConnect` when + a WebSocket server has accepted a connection request by a client. """ def __init__(self, peer, headers, version, protocol, extensions): """ @@ -477,10 +477,13 @@ class Timings: @implementer(IWebSocketChannelStreamingApi) class WebSocketProtocol: """ - Protocol base class for WebSocket. This class is used by both WebSocket - client and server protocol version. It is unusable standalone, for example - the WebSocket initial handshake is implemented in derived class differently - for clients and servers. + Protocol base class for WebSocket. + + This class implements: + + * :class:`autobahn.interfaces.IWebSocketChannel` + * :class:`autobahn.interfaces.IWebSocketChannelFrameApi` + * :class:`autobahn.interfaces.IWebSocketChannelStreamingApi` """ SUPPORTED_SPEC_VERSIONS = [0, 10, 11, 12, 13, 14, 15, 16, 17, 18] @@ -655,10 +658,7 @@ class WebSocketProtocol: def onOpen(self): """ - Callback when initial WebSocket handshake was completed. Now you may send messages. - Default implementation does nothing. Override in derived class. - - Modes: Hybi, Hixie + Implements :func:`autobahn.interfaces.IWebSocketChannel.onOpen` """ if self.debugCodePaths: self.factory._log("WebSocketProtocol.onOpen") @@ -666,13 +666,7 @@ class WebSocketProtocol: def onMessageBegin(self, isBinary): """ - Callback when receiving a new message has begun. Default implementation will - prepare to buffer message frames. Override in derived class. - - Modes: Hybi, Hixie - - :param isBinary: If True, payload is binary, otherwise text (UTF-8 encoded). - :type isBinary: bool + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageBegin` """ self.message_is_binary = isBinary self.message_data = [] @@ -681,13 +675,7 @@ class WebSocketProtocol: def onMessageFrameBegin(self, length): """ - Callback when receiving a new message frame has begun. Default implementation will - prepare to buffer message frame data. Override in derived class. - - Modes: Hybi - - :param length: Payload length of message frame which is to be received. - :type length: int + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageFrameBegin` """ self.frame_length = length self.frame_data = [] @@ -703,16 +691,7 @@ class WebSocketProtocol: def onMessageFrameData(self, payload): """ - Callback when receiving data witin message frame. Default implementation will - buffer data for frame. Override in derived class. - - Modes: Hybi, Hixie - - Notes: - - For Hixie mode, this method is slightly misnamed for historic reasons. - - :param payload: Partial payload for message frame. - :type payload: str + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageFrameData` """ if not self.failedByMe: if self.websocket_version == 0: @@ -727,11 +706,7 @@ class WebSocketProtocol: def onMessageFrameEnd(self): """ - Callback when a message frame has been completely received. Default implementation - will flatten the buffered frame data and callback onMessageFrame. Override - in derived class. - - Modes: Hybi + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageFrameEnd` """ if not self.failedByMe: self._onMessageFrame(self.frame_data) @@ -741,13 +716,7 @@ class WebSocketProtocol: def onMessageFrame(self, payload): """ - Callback fired when complete message frame has been received. Default implementation - will buffer frame for message. Override in derived class. - - Modes: Hybi - - :param payload: Message frame payload. - :type payload: list of bytestrings + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageFrame` """ if not self.failedByMe: self.message_data.extend(payload) @@ -755,11 +724,7 @@ class WebSocketProtocol: def onMessageEnd(self): """ - Callback when a message has been completely received. Default implementation - will flatten the buffered frames and callback onMessage. Override - in derived class. - - Modes: Hybi, Hixie + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessageEnd` """ if not self.failedByMe: payload = b''.join(self.message_data) @@ -772,15 +737,7 @@ class WebSocketProtocol: def onMessage(self, payload, isBinary): """ - Callback when a complete message was received. Default implementation does nothing. - Override in derived class. - - Modes: Hybi, Hixie - - :param payload: Message payload (UTF-8 encoded text string or binary string). Can also be an empty string, when message contained no payload. - :type payload: str - :param isBinary: If True, payload is binary, otherwise text. - :type isBinary: bool + Implements :func:`autobahn.interfaces.IWebSocketChannel.onMessage` """ if self.debug: self.factory._log("WebSocketProtocol.onMessage") @@ -788,13 +745,7 @@ class WebSocketProtocol: def onPing(self, payload): """ - Callback when Ping was received. Default implementation responds - with a Pong. Override in derived class. - - Modes: Hybi - - :param payload: Payload of Ping, when there was any. Can be arbitrary, up to 125 octets. - :type payload: bytes + Implements :func:`autobahn.interfaces.IWebSocketChannel.onPing` """ if self.debug: self.factory._log("WebSocketProtocol.onPing") @@ -804,13 +755,7 @@ class WebSocketProtocol: def onPong(self, payload): """ - Callback when Pong was received. Default implementation does nothing. - Override in derived class. - - Modes: Hybi - - :param payload: Payload of Pong, when there was any. Can be arbitrary, up to 125 octets. - :type payload: bytes + Implements :func:`autobahn.interfaces.IWebSocketChannel.onPong` """ if self.debug: self.factory._log("WebSocketProtocol.onPong") @@ -818,16 +763,7 @@ class WebSocketProtocol: def onClose(self, wasClean, code, reason): """ - Callback when the connection has been closed. Override in derived class. - - Modes: Hybi, Hixie - - :param wasClean: True, iff the connection was closed cleanly. - :type wasClean: bool - :param code: None or close status code (sent by peer), if there was one (:class:`WebSocketProtocol`.CLOSE_STATUS_CODE_*). - :type code: int - :param reason: None or close reason (sent by peer) (when present, a status code MUST have been also be present). - :type reason: str + Implements :func:`autobahn.interfaces.IWebSocketChannel.onClose` """ if self.debugCodePaths: s = "WebSocketProtocol.onClose:\n" @@ -1484,10 +1420,7 @@ class WebSocketProtocol: def sendPreparedMessage(self, preparedMsg): """ - Send a message that was previously prepared with - WebSocketFactory.prepareMessage(). - - Modes: Hybi, Hixie + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendPreparedMessage` """ if self.websocket_version != 0: if self._perMessageCompress is None or preparedMsg.doNotCompress: @@ -2098,14 +2031,7 @@ class WebSocketProtocol: def sendPing(self, payload = None): """ - Send out Ping to peer. A peer is expected to Pong back the payload a soon - as "practical". When more than 1 Ping is outstanding at a peer, the peer may - elect to respond only to the last Ping. - - Modes: Hybi - - :param payload: An optional, arbitrary payload of length < 126 octets. - :type payload: bytes + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendPing` """ if self.websocket_version == 0: raise Exception("function not supported in Hixie-76 mode") @@ -2122,13 +2048,7 @@ class WebSocketProtocol: def sendPong(self, payload = None): """ - Send out Pong to peer. A Pong frame MAY be sent unsolicited. - This serves as a unidirectional heartbeat. A response to an unsolicited pong is "not expected". - - Modes: Hybi - - :param payload: An optional, arbitrary payload of length < 126 octets. - :type payload: bytes + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendPong` """ if self.websocket_version == 0: raise Exception("function not supported in Hixie-76 mode") @@ -2197,17 +2117,7 @@ class WebSocketProtocol: def sendClose(self, code = None, reason = None): """ - Starts a closing handshake. - - Modes: Hybi, Hixie - - Notes: - - For Hixie mode, code and reason will be silently ignored. - - :param code: An optional close status code (:class:`WebSocketProtocol`.CLOSE_STATUS_CODE_NORMAL or 3000-4999). - :type code: int - :param reason: An optional close reason (a string that when present, a status code MUST also be present). - :type reason: str + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendClose` """ if code is not None: if type(code) != int: @@ -2229,14 +2139,7 @@ class WebSocketProtocol: def beginMessage(self, isBinary = False, doNotCompress = False): """ - Begin sending new message. - - Modes: Hybi, Hixie - - :param isBinary: Flag to indicate payload type (`True == binary`). - :type isBinary: bool - :param doNotCompress: Iff `True`, never compress this message. This only applies to Hybi-Mode and if WebSocket compression has been negotiated on the WebSocket client-server connection. Use when you know the payload is not compressible (e.g. encrypted or already compressed). - :type doNotCompress: bool + Implements :func:`autobahn.interfaces.IWebSocketChannel.beginMessage` """ if self.state != WebSocketProtocol.STATE_OPEN: return @@ -2269,16 +2172,7 @@ class WebSocketProtocol: def beginMessageFrame(self, length): """ - Begin sending new message frame. - - Modes: Hybi - - :param length: Length of frame which is started. Must be >= 0 and <= 2^63. - :type length: int - :param reserved: Reserved bits for frame (an integer from 0 to 7). Note that reserved != 0 is only legal when an extension has been negoiated which defines semantics. - :type reserved: int - :param mask: Optional frame mask. When given, this is used. When None and the peer is a client, a mask will be internally generated. For servers None is default. - :type mask: str + Implements :func:`autobahn.interfaces.IWebSocketChannel.beginMessageFrame` """ if self.websocket_version == 0: raise Exception("function not supported in Hixie-76 mode") @@ -2369,21 +2263,7 @@ class WebSocketProtocol: def sendMessageFrameData(self, payload, sync = False): """ - Send out data when within message frame (message was begun, frame was begun). - Note that the frame is automatically ended when enough data has been sent - that is, there is no endMessageFrame, since you have begun the frame specifying - the frame length, which implicitly defined the frame end. This is different from - messages, which you begin and end, since a message can contain an unlimited number - of frames. - - Modes: Hybi, Hixie - - Notes: - - For Hixie mode, this method is slightly misnamed for historic reasons. - - :param payload: Data to send. - - :returns: int -- Hybi mode: when frame still incomplete, returns outstanding octets, when frame complete, returns <= 0, when < 0, the amount of unconsumed data in payload argument. Hixie mode: returns None. + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendMessageFrameData` """ if self.state != WebSocketProtocol.STATE_OPEN: return @@ -2438,10 +2318,7 @@ class WebSocketProtocol: def endMessage(self): """ - End a message previously begun with :meth:`autobahn.websocket.WebSocketProtocol.beginMessage`. - No more frames may be sent (for that message). You have to begin a new message before sending again. - - Modes: Hybi, Hixie + Implements :func:`autobahn.interfaces.IWebSocketChannel.endMessage` """ if self.state != WebSocketProtocol.STATE_OPEN: return @@ -2467,15 +2344,7 @@ class WebSocketProtocol: def sendMessageFrame(self, payload, sync = False): """ - When a message has been previously begun with :meth:`autobahn.websocket.WebSocketProtocol.beginMessage`, - send a complete message frame in one go. - - Modes: Hybi - - :param payload: The message payload. When sending a text message, the payload must be UTF-8 encoded already. - :type payload: binary or UTF-8 string - :param sync: Iff `True`, try to force message onto wire before sending more stuff. Note: do NOT use this normally, performance likely will suffer significantly. This feature is mainly here for use by the testsuite. - :type sync: bool + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendMessageFrame` """ if self.websocket_version == 0: raise Exception("function not supported in Hixie-76 mode") @@ -2498,24 +2367,7 @@ class WebSocketProtocol: sync = False, doNotCompress = False): """ - Send out a message in one go. - - You can send text or binary message, and optionally specifiy a payload fragment size. - When the latter is given, the payload will be split up into frames with - payload <= the fragmentSize given. - - Modes: Hybi, Hixie - - :param payload: The message payload. When sending a text message (`binary == False`), the payload must be UTF-8 encoded already. - :type payload: binary or UTF-8 string - :param isBinary: Flag to indicate payload type (`True == binary`). - :type isBinary: bool - :param fragmentSize: Fragment message into fragments of this size. This overrrides `autoFragmentSize` if set. - :type fragmentSize: int - :param sync: Iff `True`, try to force message onto wire before sending more stuff. Note: do NOT use this normally, performance likely will suffer significantly. This feature is mainly here for use by the testsuite. - :type sync: bool - :param doNotCompress: Iff `True`, never compress this message. This only applies to Hybi-Mode and if WebSocket compression has been negotiated on the WebSocket client-server connection. Use when you know the payload is not compressible (e.g. encrypted or already compressed). - :type doNotCompress: bool + Implements :func:`autobahn.interfaces.IWebSocketChannel.sendMessage` """ assert(type(payload) == bytes) @@ -2662,43 +2514,39 @@ class WebSocketProtocol: class PreparedMessage: """ Encapsulates a prepared message to be sent later once or multiple - times. This is used for optimizing Broadcast/PubSub. - - The message serialization formats currently created internally are: - * Hybi - * Hixie - - The construction of different formats is needed, since we support - mixed clients (speaking different protocol versions). - - It will also be the place to add a 3rd format, when we support - the deflate extension, since then, the clients will be mixed - between Hybi-Deflate-Unsupported, Hybi-Deflate-Supported and Hixie. + times on one or more WebSocket connections. + This can be used for optimizing Broadcast/PubSub. """ - def __init__(self, payload, binary, masked, doNotCompress): + def __init__(self, payload, isBinary, applyMask, doNotCompress): """ Ctor for a prepared message. :param payload: The message payload. :type payload: str - :param binary: Provide `True` for binary payload. - :type binary: bool - :param masked: Provide `True` if WebSocket message is to be masked (required for client to server WebSocket messages). - :type masked: bool + :param isBinary: Provide `True` for binary payload. + :type isBinary: bool + :param applyMask: Provide `True` if WebSocket message is to be masked (required for client to server WebSocket messages). + :type applyMask: bool + :param doNotCompress: Iff `True`, never compress this message. This only applies to + Hybi-Mode and only when WebSocket compression has been negotiated on + the WebSocket connection. Use when you know the payload + uncompressible (e.g. encrypted or already compressed). + :type doNotCompress: bool """ if not doNotCompress: ## we need to store original payload for compressed WS - ## connections (cannot compress/frame in advanced) + ## connections (cannot compress/frame in advanced when + ## compression is on, and context takeover is off) self.payload = payload - self.binary = binary + self.binary = isBinary self.doNotCompress = doNotCompress - ## store pre-framed octets to be sent to Hixie-76 clients - self._initHixie(payload, binary) + ## store pre-framed octets to be sent to Hixie-76 peers + self._initHixie(payload, isBinary) - ## store pre-framed octets to be sent to Hybi clients - self._initHybi(payload, binary, masked) + ## store pre-framed octets to be sent to Hybi peers + self._initHybi(payload, isBinary, applyMask) def _initHixie(self, payload, binary): @@ -2803,7 +2651,7 @@ class WebSocketFactory: class WebSocketServerProtocol(WebSocketProtocol): """ - Protocol for WebSocket servers. + Protocol base class for WebSocket servers. """ CONFIG_ATTRS = WebSocketProtocol.CONFIG_ATTRS_COMMON + WebSocketProtocol.CONFIG_ATTRS_SERVER @@ -2814,15 +2662,15 @@ class WebSocketServerProtocol(WebSocketProtocol): Callback fired during WebSocket opening handshake when new WebSocket client connection is about to be established. - Throw HttpException when you don't want to accept the WebSocket - connection request. For example, throw a - `HttpException(httpstatus.http.UNAUTHORIZED[0], "You are not authorized for this!")`. - When you want to accept the connection, return the accepted protocol - from list of WebSocket (sub)protocols provided by client or None to - speak no specific one or when the client list was empty. + from list of WebSocket (sub)protocols provided by client or `None` to + speak no specific one or when the client protocol list was empty. - You may also return a pair of `(protocol, headers)` to send additional HTTP `headers`. + You may also return a pair of `(protocol, headers)` to send additional + HTTP headers, with `headers` being a dictionary of key-values. + + Throw :class:`autobahn.websocket.http.HttpException` when you don't want + to accept the WebSocket connection request. :param request: WebSocket connection request information. :type request: instance of :class:`autobahn.websocket.protocol.ConnectionRequest` @@ -3442,12 +3290,12 @@ class WebSocketServerProtocol(WebSocketProtocol): class WebSocketServerFactory(WebSocketFactory): """ - A protocol factory for WebSocket server protocols. + A protocol factory for WebSocket servers. """ protocol = WebSocketServerProtocol """ - The protocol to be spoken. Must be derived from :class:`autobahn.websocket.WebSocketServerProtocol`. + The protocol to be spoken. Must be derived from :class:`autobahn.websocket.protocol.WebSocketServerProtocol`. """ isServer = True @@ -3468,22 +3316,22 @@ class WebSocketServerFactory(WebSocketFactory): Create instance of WebSocket server factory. Note that you MUST provide URL either here or using - :meth:`autobahn.websocket.WebSocketServerFactory.setSessionParameters` + :meth:`autobahn.websocket.protocol.WebSocketServerFactory.setSessionParameters` *before* the factory is started. - :param url: WebSocket listening URL - ("ws:" | "wss:") "//" host [ ":" port ]. + :param url: The WebSocket URL this factory is working for, e.g. `ws://myhost.com/somepath`. :type url: str :param protocols: List of subprotocols the server supports. The subprotocol used is the first from the list of subprotocols announced by the client that is contained in this list. :type protocols: list of strings - :param server: Server as announced in HTTP response header during opening handshake or None (default: "AutobahnWebSocket/x.x.x"). + :param server: Server as announced in HTTP response header during opening handshake or None (default: `AutobahnWebSocket/?.?.?`). :type server: str :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake. :type headers: dict - :param externalPort: Optionally, the external visible port this server will be reachable under (i.e. when running behind a L2/L3 forwarding device). + :param externalPort: Optionally, the external visible port this factory will be reachable under (i.e. when running behind a L2/L3 forwarding device). :type externalPort: int - :param debug: Debug mode (default: False). + :param debug: Debug mode (default: `False`). :type debug: bool - :param debugCodePaths: Debug code paths mode (default: False). + :param debugCodePaths: Debug code paths mode (default: `False`). :type debugCodePaths: bool """ self.debug = debug @@ -3519,7 +3367,7 @@ class WebSocketServerFactory(WebSocketFactory): """ Set WebSocket session parameters. - :param url: WebSocket listening URL - ("ws:" | "wss:") "//" host [ ":" port ]. + :param url: The WebSocket URL this factory is working for, e.g. `ws://myhost.com/somepath`. :type url: str :param protocols: List of subprotocols the server supports. The subprotocol used is the first from the list of subprotocols announced by the client that is contained in this list. :type protocols: list of strings @@ -3598,35 +3446,35 @@ class WebSocketServerFactory(WebSocketFactory): """ Set WebSocket protocol options used as defaults for new protocol instances. - :param versions: The WebSocket protocol versions accepted by the server (default: WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS). + :param versions: The WebSocket protocol versions accepted by the server (default: :func:`autobahn.websocket.protocol.WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS`). :type versions: list of ints :param allowHixie76: Allow to speak Hixie76 protocol version. :type allowHixie76: bool - :param webStatus: Return server status/version on HTTP/GET without WebSocket upgrade header (default: True). + :param webStatus: Return server status/version on HTTP/GET without WebSocket upgrade header (default: `True`). :type webStatus: bool - :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: True). + :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: `True`). :type utf8validateIncoming: bool - :param maskServerFrames: Mask server-to-client frames (default: False). + :param maskServerFrames: Mask server-to-client frames (default: `False`). :type maskServerFrames: bool - :param requireMaskedClientFrames: Require client-to-server frames to be masked (default: True). + :param requireMaskedClientFrames: Require client-to-server frames to be masked (default: `True`). :type requireMaskedClientFrames: bool - :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and incoming frames (default: True). + :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and incoming frames (default: `True`). :type applyMask: bool - :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or 0 for unlimited (default: 0). + :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or `0` for unlimited (default: `0`). :type maxFramePayloadSize: int - :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that will be accepted when receiving or 0 for unlimited (default: 0). + :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that will be accepted when receiving or `0` for unlimited (default: `0`). :type maxMessagePayloadSize: int - :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API) into frames with payload length <= this size or 0 for no auto-fragmentation (default: 0). + :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API) into frames with payload length `<=` this size or `0` for no auto-fragmentation (default: `0`). :type autoFragmentSize: int - :param failByDrop: Fail connections by dropping the TCP connection without performaing closing handshake (default: True). + :param failByDrop: Fail connections by dropping the TCP connection without performaing closing handshake (default: `True`). :type failbyDrop: bool - :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply with code == NORMAL, reason = "" (default: False). + :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply with `code == 1000, reason = ""` (default: `False`). :type echoCloseCodeReason: bool - :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or 0 to deactivate (default: 0). + :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or `0` to deactivate (default: `0`). :type openHandshakeTimeout: float - :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout in seconds (default: 1). + :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout in seconds (default: `1`). :type closeHandshakeTimeout: float - :param tcpNoDelay: TCP NODELAY ("Nagle") socket option (default: True). + :param tcpNoDelay: TCP NODELAY ("Nagle") socket option (default: `True`). :type tcpNoDelay: bool :param perMessageCompressionAccept: Acceptor function for offers. :type perMessageCompressionAccept: callable @@ -3698,7 +3546,7 @@ class WebSocketServerFactory(WebSocketFactory): class WebSocketClientProtocol(WebSocketProtocol): """ - Client protocol for WebSocket. + Protocol base class for WebSocket clients. """ CONFIG_ATTRS = WebSocketProtocol.CONFIG_ATTRS_COMMON + WebSocketProtocol.CONFIG_ATTRS_CLIENT @@ -4187,12 +4035,12 @@ class WebSocketClientProtocol(WebSocketProtocol): class WebSocketClientFactory(WebSocketFactory): """ - A protocol factory for WebSocket client protocols. + A protocol factory for WebSocket clients. """ protocol = WebSocketClientProtocol """ - The protocol to be spoken. Must be derived from :class:`autobahn.websocket.WebSocketClientProtocol`. + The protocol to be spoken. Must be derived from :class:`autobahn.websocket.protocol.WebSocketClientProtocol`. """ isServer = False @@ -4217,21 +4065,21 @@ class WebSocketClientFactory(WebSocketFactory): :meth:`autobahn.websocket.WebSocketClientFactory.setSessionParameters` *before* the factory is started. - :param url: WebSocket URL to connect to - ("ws:" | "wss:") "//" host [ ":" port ] path [ "?" query ]. + :param url: WebSocket URL this factory will connect to, e.g. `ws://myhost.com/somepath`. :type url: str - :param origin: The origin to be sent in WebSocket opening handshake or None (default: None). + :param origin: The origin to be sent in WebSocket opening handshake or None (default: `None`). :type origin: str - :param protocols: List of subprotocols the client should announce in WebSocket opening handshake (default: []). + :param protocols: List of subprotocols the client should announce in WebSocket opening handshake (default: `[]`). :type protocols: list of strings - :param useragent: User agent as announced in HTTP request header or None (default: "AutobahnWebSocket/x.x.x"). + :param useragent: User agent as announced in HTTP request header or None (default: `AutobahnWebSocket/?.?.?`). :type useragent: str :param headers: An optional mapping of additional HTTP headers to send during the WebSocket opening handshake. :type headers: dict - :param proxy: Explicit proxy server to use (hostname:port or IP:port), e.g. "192.168.1.100:8080". + :param proxy: Explicit proxy server to use (`hostname:port` or `IP:port`), e.g. `192.168.1.100:8080`. :type proxy: str - :param debug: Debug mode (default: False). + :param debug: Debug mode (default: `False`). :type debug: bool - :param debugCodePaths: Debug code paths mode (default: False). + :param debugCodePaths: Debug code paths mode (default: `False`). :type debugCodePaths: bool """ self.debug = debug @@ -4264,7 +4112,7 @@ class WebSocketClientFactory(WebSocketFactory): """ Set WebSocket session parameters. - :param url: WebSocket URL to connect to - ("ws:" | "wss:") "//" host [ ":" port ] path [ "?" query ]. + :param url: WebSocket URL this factory will connect to, e.g. `ws://myhost.com/somepath`. :type url: str :param origin: The origin to be sent in opening handshake. :type origin: str @@ -4349,32 +4197,32 @@ class WebSocketClientFactory(WebSocketFactory): """ Set WebSocket protocol options used as defaults for _new_ protocol instances. - :param version: The WebSocket protocol spec (draft) version to be used (default: WebSocketProtocol.DEFAULT_SPEC_VERSION).l - :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: True). + :param version: The WebSocket protocol spec (draft) version to be used (default: :func:`autobahn.websocket.protocol.WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS`). + :param utf8validateIncoming: Validate incoming UTF-8 in text message payloads (default: `True`). :type utf8validateIncoming: bool - :param acceptMaskedServerFrames: Accept masked server-to-client frames (default: False). + :param acceptMaskedServerFrames: Accept masked server-to-client frames (default: `False`). :type acceptMaskedServerFrames: bool - :param maskClientFrames: Mask client-to-server frames (default: True). + :param maskClientFrames: Mask client-to-server frames (default: `True`). :type maskClientFrames: bool - :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and incoming frames (default: True). + :param applyMask: Actually apply mask to payload when mask it present. Applies for outgoing and incoming frames (default: `True`). :type applyMask: bool - :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or 0 for unlimited (default: 0). + :param maxFramePayloadSize: Maximum frame payload size that will be accepted when receiving or `0` for unlimited (default: `0`). :type maxFramePayloadSize: int - :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that will be accepted when receiving or 0 for unlimited (default: 0). + :param maxMessagePayloadSize: Maximum message payload size (after reassembly of fragmented messages) that will be accepted when receiving or `0` for unlimited (default: `0`). :type maxMessagePayloadSize: int - :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API) into frames with payload length <= this size or 0 for no auto-fragmentation (default: 0). + :param autoFragmentSize: Automatic fragmentation of outgoing data messages (when using the message-based API) into frames with payload length `<=` this size or `0` for no auto-fragmentation (default: `0`). :type autoFragmentSize: int - :param failByDrop: Fail connections by dropping the TCP connection without performing closing handshake (default: True). + :param failByDrop: Fail connections by dropping the TCP connection without performing closing handshake (default: `True`). :type failbyDrop: bool - :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply with code == NORMAL, reason = "" (default: False). + :param echoCloseCodeReason: Iff true, when receiving a close, echo back close code/reason. Otherwise reply with `code == 1000, reason = ""` (default: `False`). :type echoCloseCodeReason: bool - :param serverConnectionDropTimeout: When the client expects the server to drop the TCP, timeout in seconds (default: 1). + :param serverConnectionDropTimeout: When the client expects the server to drop the TCP, timeout in seconds (default: `1`). :type serverConnectionDropTimeout: float - :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or 0 to deactivate (default: 0). + :param openHandshakeTimeout: Opening WebSocket handshake timeout, timeout in seconds or `0` to deactivate (default: `0`). :type openHandshakeTimeout: float - :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout in seconds (default: 1). + :param closeHandshakeTimeout: When we expect to receive a closing handshake reply, timeout in seconds (default: `1`). :type closeHandshakeTimeout: float - :param tcpNoDelay: TCP NODELAY ("Nagle"): bool socket option (default: True). + :param tcpNoDelay: TCP NODELAY ("Nagle"): bool socket option (default: `True`). :type tcpNoDelay: bool :param perMessageCompressionOffers: A list of offers to provide to the server for the permessage-compress WebSocket extension. Must be a list of instances of subclass of PerMessageCompressOffer. :type perMessageCompressionOffers: list of instance of subclass of PerMessageCompressOffer diff --git a/doc/README.md b/doc/README.md index 586f814d..e676cd65 100644 --- a/doc/README.md +++ b/doc/README.md @@ -9,6 +9,7 @@ The documentation is generated automatically from the Python source file via [Sp To generate the documentation yourself, you will need to install Sphinx: easy_install sphinx + easy_install repoze.sphinx.autointerface and then diff --git a/doc/conf.py b/doc/conf.py index 387538b0..35ea1997 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -25,7 +25,11 @@ import sys, os # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc'] +#extensions = ['sphinx.ext.autodoc'] + +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'repoze.sphinx.autointerface'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/doc/index.rst b/doc/index.rst index 61eba97e..d4b8b8e8 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,10 +1,10 @@ -AutobahnPython Reference -======================== +************************* +Autobahn|Python Reference +************************* .. toctree:: :maxdepth: 3 - features websockettoc wamptoc diff --git a/doc/twistedintegration.rst b/doc/twistedintegration.rst new file mode 100644 index 00000000..0a509368 --- /dev/null +++ b/doc/twistedintegration.rst @@ -0,0 +1,86 @@ +******************* +Twisted Integration +******************* + +Autobahn|Python provides the following functions and classes for further Twisted integration. + + + +Connect & Listen +================ + +.. autofunction:: autobahn.twisted.websocket.connectWS + +.. autofunction:: autobahn.twisted.websocket.listenWS + +| + +Twisted Reactor +=============== + +.. autofunction:: autobahn.twisted.choosereactor.install_optimal_reactor + +.. autofunction:: autobahn.twisted.choosereactor.install_reactor + +| + +Wrapping Factory & Protocol +=========================== + +You can find a complete example `here `_ + + +.. autoclass:: autobahn.twisted.websocket.WrappingWebSocketServerFactory + :show-inheritance: + :members: __init__ + +.. autoclass:: autobahn.twisted.websocket.WrappingWebSocketClientFactory + :show-inheritance: + :members: __init__ + +| + +Twisted Endpoints +================= + +You can find a complete example `here `_ + +| + +Twisted Web & WSGI +================== + +AutobahnPython provides integration with Twisted Web via a special `WebSocketResource` that can be added to Twisted Web resource hierarchies. + +You can find a complete example `here `_ + +.. autoclass:: autobahn.twisted.resource.WebSocketResource + :members: __init__, + getChildWithDefault, + putChild, + render + +.. autoclass:: autobahn.twisted.resource.HTTPChannelHixie76Aware + +| + +The Twisted Web support of AutobahnPython also allows you add WebSocket as part of a WSGI application that runs under Twisted. + +You can find a complete example `here `_ + +.. autoclass:: autobahn.twisted.resource.WSGIRootResource + :members: __init__ + +| + +Flash Policy Server +=================== + +You can find a complete example `here `_ + + +.. autoclass:: autobahn.twisted.flashpolicy.FlashPolicyProtocol + :members: __init__ + +.. autoclass:: autobahn.twisted.flashpolicy.FlashPolicyFactory + :members: __init__ diff --git a/doc/websocketaux.rst b/doc/websocketaux.rst index 7bc964c0..abd98f16 100644 --- a/doc/websocketaux.rst +++ b/doc/websocketaux.rst @@ -1,63 +1,28 @@ -Auxiliary -========= +******************* +WebSocket Auxiliary +******************* The classes and functions here provide auxiliary and supporting functionality to the WebSocket implementation. -Connect & Listen ----------------- - -.. autofunction:: autobahn.twisted.websocket.connectWS - -.. autofunction:: autobahn.twisted.websocket.listenWS - - URL Handling ------------- +============ .. autofunction:: autobahn.websocket.protocol.createWsUrl .. autofunction:: autobahn.websocket.protocol.parseWsUrl -Opening Handshake ------------------ - -.. autoclass:: autobahn.websocket.http.HttpException - :members: __init__ - - -Twisted Web Integration ------------------------ - -.. autoclass:: autobahn.twisted.resource.WebSocketResource - :members: __init__, - getChildWithDefault, - putChild, - render - -.. autoclass:: autobahn.twisted.resource.WSGIRootResource - :members: __init__ - -.. autoclass:: autobahn.twisted.resource.HTTPChannelHixie76Aware - - -Flash Policy File Server ------------------------- - -.. autoclass:: autobahn.twisted.flashpolicy.FlashPolicyProtocol - :members: __init__ - -.. autoclass:: autobahn.twisted.flashpolicy.FlashPolicyFactory - :members: __init__ - - -Misc ----- +User Agents +=========== .. autofunction:: autobahn.websocket.useragent.lookupWsSupport + +Traffic Statistics +================== + .. autoclass:: autobahn.websocket.protocol.Timings :members: __init__, track, diff --git a/doc/websocketcompress.rst b/doc/websocketcompress.rst index 650e8363..3172e47e 100644 --- a/doc/websocketcompress.rst +++ b/doc/websocketcompress.rst @@ -1,94 +1,109 @@ -Compression -=========== +********************* +WebSocket Compression +********************* -AutobahnPython supports the following WebSocket extensions for compression: +Autobahn|Python supports the following WebSocket extensions for compression: - * `permessage-deflate` - * `permessage-bzip2` - * `permessage-snappy` + * `permessage-deflate `_ + * permessage-bzip2 + * permessage-snappy + +You can find a complete example `here `_. | -Per-Message Deflate Compression -------------------------------- +Per-Message Deflate +=================== -The following classes provide the API to the `permessage-deflate` WebSocket extension functionality of AutobahnPython. +The following classes provide the API to the **permessage-deflate** WebSocket extension functionality of AutobahnPython. | .. autoclass:: autobahn.websocket.compress.PerMessageDeflateOffer + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageDeflateOfferAccept + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageDeflateResponse + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageDeflateResponseAccept + :show-inheritance: :members: __init__, __json__, __repr__ | -Per-Message Bzip2 Compression ------------------------------ +Per-Message Bzip2 +================= -The following classes provide the API to the `permessage-bzip2` WebSocket extension functionality of AutobahnPython. +The following classes provide the API to the (non-standard) **permessage-bzip2** WebSocket extension functionality of Autobahn|Python. | .. autoclass:: autobahn.websocket.compress.PerMessageBzip2Offer + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageBzip2OfferAccept + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageBzip2Response + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageBzip2ResponseAccept + :show-inheritance: :members: __init__, __json__, __repr__ | -Per-Message Snappy Compression ------------------------------- +Per-Message Snappy +================== -The following classes provide the API to the `permessage-snappy` WebSocket extension functionality of AutobahnPython. +The following classes provide the API to the (non-standard) **permessage-snappy** WebSocket extension functionality of Autobahn|Python. | .. autoclass:: autobahn.websocket.compress.PerMessageSnappyOffer + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageSnappyOfferAccept + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageSnappyResponse + :show-inheritance: :members: __init__, __json__, __repr__ | .. autoclass:: autobahn.websocket.compress.PerMessageSnappyResponseAccept + :show-inheritance: :members: __init__, __json__, __repr__ | diff --git a/doc/websocketintro.rst b/doc/websocketintro.rst index ed028be5..02657173 100644 --- a/doc/websocketintro.rst +++ b/doc/websocketintro.rst @@ -1,61 +1,76 @@ +************ Introduction -============ +************ -The class :class:`autobahn.websocket.protocol.WebSocketProtocol` implements the -WebSocket protocol. +Basic WebSocket +=============== -Though you will use methods and override callbacks from this class, you must -implement your clients/servers by deriving from the classes -:class:`autobahn.websocket.protocol.WebSocketClientProtocol` and -:class:`autobahn.websocket.protocol.WebSocketServerProtocol`. +**AutobahnPython** provides a Message-based API to WebSocket plus auxiliary methods and callbacks. + +The message-based API closely resembles the API of WebSocket available to JavaScript in browsers. + +Most of the time, this API is what you should use, unless you have specific needs (frame-based / streaming processing, see below). -Class Diagrams --------------- +Message-based Processing +------------------------ - -* :class:`autobahn.websocket.protocol.WebSocketProtocol` -* :class:`autobahn.websocket.protocol.WebSocketClientProtocol` -* :class:`autobahn.websocket.protocol.WebSocketServerProtocol` -* :class:`autobahn.wamp.WampClientProtocol` -* :class:`autobahn.wamp.WampServerProtocol` - -.. image:: protocolclasses.png - - -* :class:`autobahn.websocket.protocol.WebSocketClientFactory` -* :class:`autobahn.websocket.protocol.WebSocketServerFactory` -* :class:`autobahn.wamp.WampClientFactory` -* :class:`autobahn.wamp.WampServerFactory` - -.. image:: factoryclasses.png - - -Basic API ---------- - -Most of the time, the basic API offered by *AutobahnPython* -will be the one you want to use. It is easy to use and gets out of your way. - -The basic API is the one to use, unless you have specific needs (frame-based -processing or streaming), in which case Autobahn provides an advanced -API (see below). - -The basic API consists of the following methods and callbacks +The message-based API is implemented in the following methods and callbacks * :func:`autobahn.websocket.protocol.WebSocketProtocol.onOpen` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessage` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.onClose` * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendMessage` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessage` * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendClose` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.onClose` -Advanced API ------------- +Prepared Messages +----------------- + +In case you want to send a single WebSocket message to multiple peers, AutobahnPython provides an optimized way of sending using + + * :func:`autobahn.websocket.protocol.WebSocketFactory.prepareMessage` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPreparedMessage` + + +Handshake Hooks +--------------- + +AutobahnPython allows you to hook into the initial WebSocket opening handshake (e.g. for handling HTTP cookies, subprotocols, etc): + + * :func:`autobahn.websocket.protocol.WebSocketServerProtocol.onConnect` + * :func:`autobahn.websocket.protocol.WebSocketClientProtocol.onConnect` + + +Ping/Pong Processing +-------------------- + +The basic API also allows for explicit processing of WebSocket Pings and Pongs: + + * :func:`autobahn.websocket.protocol.WebSocketProtocol.onPing` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.onPong` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPing` + * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPong` + +Note that explicit processing of Pings/Pongs is unnecessary normally - AutobahnPython will do the right thing under the hood. + + +Interface Definition +-------------------- + +The basic API has the following interface definition: + +.. autointerface:: autobahn.interfaces.IWebSocketChannel + :members: + + + +Advanced WebSocket +================== A WebSockets message consists of a potentially unlimited number of -fragments ("message frames"), each of which can have a payload between 0 -and 2^63 octets. +fragments ("message frames"), each of which can have a payload between `0` +and `2^63` octets. The implementation of the basic API is message-based, and thus has to buffer all data received for a message frame, and buffer all frames received for @@ -63,7 +78,7 @@ a message, and only when the message finally ends, flattens all buffered data and fires :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessage`. Usually, when you produce/consume messages of small to limited size (like -say <256k), this is absolutely sufficient and convenient. +say `<256k`), this is absolutely sufficient and convenient. However, when you want to process messages consisting of a large number of message fragments, or you want to process messages that contain message @@ -77,11 +92,12 @@ The advanced API provides you all the necessary methods and callbacks to do WebSockets using frame-based processing or even completely streaming processing - both sending and receiving. -API for prepared message processing: - * :func:`autobahn.websocket.protocol.WebSocketFactory.prepareMessage` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPreparedMessage` -API for frame-based processing: + +Frame-based API +--------------- + +API for frame-based processing is implemented in: * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessageBegin` * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessageFrame` @@ -90,7 +106,16 @@ API for frame-based processing: * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendMessageFrame` * :func:`autobahn.websocket.protocol.WebSocketProtocol.endMessage` -API for streaming processing: +and has the following definition: + +.. autointerface:: autobahn.interfaces.IWebSocketChannelFrameApi + :members: + + +Streaming API +------------- + +API for streaming processing is implemented in: * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessageBegin` * :func:`autobahn.websocket.protocol.WebSocketProtocol.onMessageFrameBegin` @@ -102,19 +127,7 @@ API for streaming processing: * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendMessageFrameData` * :func:`autobahn.websocket.protocol.WebSocketProtocol.endMessage` -The advanced API for frame-based/streaming processing of WebSockets -messages also provides access to extension points in the WebSockets -protocol (you also normally won't use) - namely "reserved bits" and -"reserved opcodes". +and has the following definition: -Additionally, the advanced API provides methods and callbacks to do -your own processing of WebSockets Pings and Pongs. Normally, it is -unnecessary to do that, Autobahn will do the right thing under the hood. -Anyway, if you want, you can do. - -API for explicit Ping/Pong processing: - - * :func:`autobahn.websocket.protocol.WebSocketProtocol.onPing` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.onPong` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPing` - * :func:`autobahn.websocket.protocol.WebSocketProtocol.sendPong` +.. autointerface:: autobahn.interfaces.IWebSocketChannelStreamingApi + :members: diff --git a/doc/websocketserver.rst b/doc/websocketserver.rst index 6b896983..408b87ca 100644 --- a/doc/websocketserver.rst +++ b/doc/websocketserver.rst @@ -30,6 +30,9 @@ Both Twisted and Asyncio server protocols share the following functionality. .. autoclass:: autobahn.websocket.protocol.ConnectionRequest :members: __init__ +.. autoclass:: autobahn.websocket.http.HttpException + :members: __init__ + Twisted WebSocket Server Protocol --------------------------------- diff --git a/doc/websockettoc.rst b/doc/websockettoc.rst index aaa1513c..b281d004 100644 --- a/doc/websockettoc.rst +++ b/doc/websockettoc.rst @@ -8,5 +8,6 @@ WebSocket websocketbase websocketclient websocketserver - websocketaux websocketcompress + websocketaux + twistedintegration