Awesome
#WSOCK
About <a name="about"></a>
Wsock are a set of modules that can be used to build Websockets (RFC 6455 compliant) clients an servers.
Examples <a name="examples"></a>
wsserver (a WebSockets server) and wsecli (a WebSockets client) are projects which use wsock.
Writing clients <a name="usge_clients"></a>
Don't forguet to include the wsock headers file:
-include_lib("wsock/include/wsock.hrl").
Upgrading the connection <a name="upgrading_client"></a>
Create and send an upgrade request to the server.
-
Build a handshake request:
HandshakeRequest = wsock_handshake:open(Resource, Host, Port)
-
Encode the handshake to send it to the server:
BinaryData = wsock_http:encode(HandshakeRequest#handshake.message)
-
Receive and validate the handshake response:
{ok, HandshakeResponse} = wsock_http:decode(Data, response) wsock_handshake:handle_response(HandshakeResponse, HandshakeRequest)
If the received HTTP message is fragmented
wsock_http:decode
will return the atomfragmented_http_message
. Check the section upgrading the connection when writing servers for more info.
Sending data <a name="client_sending"></a>
Once the connection has been stablished you can send data through it:
Message = wsock_message:encode(Data, [mask, text]) %text data
Message = wsock_message:encode(Data, [mask, binary]) %binary data
Receiving data <a name="client_receiving"></a>
-
If there is no previous fragmented message:
ListOfMessages = wsock_message:decode(Data, [])
-
If the previously received message was fragmented pass it as a parameter:
ListOfMessages = wsock_message:decode(Data, FragmentedMessage, [])
Check wsock.hrl
for a description of the message record.
Control messages <a name="client_control_messages"></a>
-
Ping/pong messages:
ListOfMessages = wsock_message:encode(Data, [mask, ping]) ListOfMessages = wsock_message:encode(Data, [mask, pong])
-
Close messages (with or without reason):
ListOfMessages = wsock_message:encode({StatusCode, Payload}, [mask, close]) ListOfMessages = wsock_message:encode([]], [close]) % If no payload
Writing servers <a name="usage_servers"></a>
Don't forget to include the wsock headers file:
-include_lib("wsock/include/wsock.hrl").
Upgrading the connection <a name="upgrading_server"></a>
Accept upgrade requests from your clients.
-
Decode the http-handshake request:
{ok, OpenHttpMessage} = wsock_http:decode(Data, request), {ok, OpenHandshake} = wsock_handshake:handle_open(OpenHttpMessage)
If the received HTTP message is fragmented
wsock_http:decode
will return the atomfragmented_http_message
. In this case, buffer the partial HTTP message until more data is received and try again.fragmented_http_message = wsock_http:decode(Data, request), %% Buffer Data %% … some time passes and then more data is received %% Concat the new data to the buffered one and pass it to wsock_http:decode {ok, OpenHttpMessage} = wsock_http:decode(<<Buffered/binary, NewData/binary>>, request), …
-
Get handshake key to generate a handshake response:
ClientWSKey = wsock_http:get_header_value("sec-websocket-key", OpenHandshake#handshake.message), {ok, HandshakeResponse} = wsock_handshake:response(ClientWSKey)
-
Encode the http-handshake response:
ResponseHttpMessage = wsock_http:encode(HandshakeResponse#handshake.message)
Now all you have to do is send the handshake response over the wire to upgrade the HTTP connection to a WebSockets one.
Receiving data <a name="receiving_server"></a>
-
If there is no previous fragmented message:
ListOfMessages = wsock_message:decode(Data, [masked])
-
If the previously received message was fragmented pass it as a parameter:
ListOfMessages = wsock_message:decode(Data, FragmentedMessage, [masked])
Check wsock.hrl for a description of the message record.
Sending data <a name="sending_server"></a>
Once the connection has been stablished you can send data through it:
ListOfMessages = wsock_message:encode(Data, [text]) % text data, servers don't mask data
ListOfMessages = wsock_message:encode(Data, [binary]) % binary data
Control messages <a name="server_control_messages"></a>
-
Ping/pong messages:
ListOfMessages = wsock_message:encode(Data, [ping]) ListOfMessages = wsock_message:encode(Data, [pong])
-
Close messages (with or without reason):
ListOfMessages = wsock_message:encode({StatusCode, Payload}, [close]) ListOfMessages = wsock_message:encode([]], [close]) % If no payload
Documentation <a name="documentation"></a>
Documentation for the modules can be generated. Run:
rake doc
or, in case you don't have rake installed:
rebar doc
Tests <a name="tests"></a>
Unit test where done with the library espec by lucaspiller. To run them:
rake spec
or, in case you don't have rake installed:
rebar compile && ERL_LIBS='deps/' ./espec test/spec/
Contribute <a name="contributing"></a>
If you find or think that something isn't working properly, just open an issue.
Pull requests and patches (with tests) are welcome.
Author <a name="author"></a>
This stuff has been writen by Farruco sanjurjo
- @madtrick at twitter
- Email at madtrick@gmail.com
License <a name="license"></a>
Copyright [2012] [Farruco Sanjurjo Arcay]
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.