Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Erlang library to build WebSocket clients and servers

branch: master
README.md

Analytics

WSOCK

About

Wsock are a set of modules that can be used to build Websockets (RFC 6455 compliant) clients an servers.

Examples

wsserver (a WebSockets server) and wsecli (a WebSockets client) are projects which use wsock.

Writing clients

Don't forguet to include the wsock headers file:

  -include_lib("wsock/include/wsock.hrl").

Upgrading the connection

Create and send an upgrade request to the server.

  1. Build a handshake request:

    HandshakeRequest = wsock_handshake:open(Resource, Host, Port)
    
  2. Encode the handshake to send it to the server:

     BinaryData = wsock_http:encode(HandshakeRequest#handshake.message)
    
  3. 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 atom fragmented_http_message. Check the section upgrading the connection when writing servers for more info.

Sending data

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

  • 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

  • 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

Don't forget to include the wsock headers file:

  -include_lib("wsock/include/wsock.hrl").

Upgrading the connection

Accept upgrade requests from your clients.

  1. 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 atom fragmented_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),
    
    
  2. 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)
    
  3. 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

  • 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

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

  • 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

Documentation for the modules can be generated. Run:

  rake doc

or, in case you don't have rake installed:

  rebar doc

Tests

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

If you find or think that something isn't working properly, just open an issue.

Pull requests and patches (with tests) are welcome.

Author

This stuff has been writen by Farruco sanjurjo

License

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.

Something went wrong with that request. Please try again.