#WSOCK
Wsock are a set of modules that can be used to build Websockets (RFC 6455 compliant) clients an servers.
wsserver (a WebSockets server) and wsecli (a WebSockets client) are projects which use wsock.
Don't forguet to include the wsock headers file:
-include_lib("wsock/include/wsock.hrl").
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.
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
-
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.
-
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
Don't forget to include the wsock headers file:
-include_lib("wsock/include/wsock.hrl").
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.
-
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.
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
-
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 for the modules can be generated. Run:
rake doc
or, in case you don't have rake installed:
rebar doc
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/
If you find or think that something isn't working properly, just open an issue.
Pull requests and patches (with tests) are welcome.
This stuff has been writen by Farruco sanjurjo
- @madtrick at twitter
- Email at madtrick@gmail.com
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.