Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

A protocol agnostic tcp/ip gateway that runs in the upper layer of the OSI stack

branch: master
README.md

linedancer

This was an early experiment with Erlang/OTP, for something more production ready you should checkout extend/ranch.

A protocol agnostic tcp/ip gateway that runs in the upper layer of the OSI stack

Introduction

Linedancer is a little framework for creating non-blocking TCP/IP servelrs based roughly based on the writings of Serge Aleynikov (http://www.trapexit.org/Building_a_Non-blocking_TCP_server_using_OTP_principles).

The server is just a library which you can include in your application, in it's most basic form you can start the supervisor directly:

linedancer_sup:start_link([{port, 7000}, {protocol_handler, protocolfsm}]).

This will start a supervisor accepting new connections (linedancer_socket) which in turn creates a new process for handling the data (linedancer_client_fsm), your implementation is wrapped around the last part. If you want to change the client handler this can be specified as an option to the supervisor {client_handler, <module>}

Examples

Linedancer comes with 2 example implementations. To run any of the examples you can use the following commands (requires http://github.com/basho/rebar):

$ git clone git://github.com/lafka/linedancer.git
$ cd linedancer
$ rebar compile
$ cd examples/<example>
$ rebar compile
$ erl -pa ebin -pa ../../ebin -boot start_sasl -s <example>

You can now access the example server by using telnet, socat, netcat or whatever tool you prefer:

netcat localhost 7000
# telnet localhost 7000
# Connected to localhost.
# Escape character is '^]'.
# G`day
# G`day

Creating your own protocol

To create your own protocol you need to create your own protocol handler, this is done by using the gen_fsm behaviour:

-module(myprotocol).

-behaviour(gen_fsm).

%% ... removed for readability ...

%% The initial state is set by the return value of init/1
init(_) ->
    {ok, 'INIT', #state{}}.

'INIT'({_, Socket}, _Ref, State) ->
    {reply, ok, 'RECV', State#state{socket = Socket}}.

'RECV'({_, Socket, Buf}, _Ref, State = #state{socket = Socket}) ->
    gen_tcp:send(Socket, Buf),
    {reply, ok, 'RECV', State}.

%% ... removed for readability ...

When you have your protocol module up, just point protocol_handler in your ''*.app file'' to the name of your module and it should start serving data.

Performance

No real benchmarks on how this actually performs in a production setting, local testing with a minimal protocol runs around 25K req/s.

Something went wrong with that request. Please try again.