豬頭 (beezari) wrote,
豬頭
beezari

socket proxy in erlang

Since I started spitting out some code here, here's another thing I've been playing recently. Erlang. For kicks, I decided to implement a socket proxy/connection bouncer. The erlang socket programming model is slightly different from the ones we used to in python/c/perl/... so here is the piece (docs and original example here:
http://www.erlang.org/doc/man/gen_tcp.html

Interesting things to pay attention on:

you are only going to get data via messages (receive statement) if you use active socket. w/ passive socket you'll have to fetch it with recv.

{packet,0} - means you're getting raw data. it is also possible to request for pre-packaged data (see avail. options at http://www.erlang.org/doc/man/inet.html#setopts-2).

Anyways,
1-2:erl fygrave$ cat socket_proxy.erl
-module(socket_proxy).

-export([
	 start/4,
	 server/3,
	 process/1,
         loop/2
]).
%
% once compiled, start it like socket_proxy:start(20, 1222, "somehost", 22).
%
start(Num,LPort, Host, DPort) ->
    case gen_tcp:listen(LPort,[{active, true},{packet,0}]) of
        {ok, ListenSock} ->
            start_servers(Num,ListenSock, Host, DPort),
            {ok, Port} = inet:port(ListenSock),
            Port;
        {error,Reason} ->
            {error,Reason}
    end.
start_servers(0,_, _, _) ->
    ok;
start_servers(Num,LS, Host, DPort) ->
    spawn(?MODULE,server,[LS, Host, DPort]),
    start_servers(Num-1,LS, Host, DPort).
server(LS, Host, DPort) ->
    io:format("Server started ~n"),
    case gen_tcp:accept(LS) of
        {ok,S} ->
            io:format("Got connect ~n"),
            case gen_tcp:connect(Host, DPort,
				 [binary, 
		     {packet,0},
		     {active, true}
                    ]
				) of
		{ok, Socket} ->
		    loop(S,Socket),
		    server(LS,Host, DPort);
		E ->
		    io:format("Error:Connect failed!~n"),
		    E
		end,
		ok;
        Other ->
            io:format("Error: accept returned ~w - finita!~n",[Other]),
            ok
    end.
loop(S,Socket) ->
    inet:setopts(S,[{active,once}]),
    receive
        {tcp,S,Data} ->
	    io:format("Received tcp ~p ~n",[Data]),
            Ret = process(Data), % you can poke around with the data
            gen_tcp:send(Socket,Ret),
            loop(S, Socket); % erlang awesomeness. no loops ;)
        {tcp,Socket,Data} ->
            io:format("Received tcp(S) ~p ~n", [Data]),
            Ret = process(Data),
            gen_tcp:send(S, Ret),
            loop(S,Socket);
        {tcp_closed,S} ->
            gen_tcp:close(Socket),
            io:format("Socket ~w closed [~w]~n",[S,self()]),
            ok;
        {tcp_closed, Socket}->
            gen_tcp:close(S),
            io:format("Socket (S) ~w closed [~w]~n",[S,self()]),
            ok
	
    end.

process(Data) ->
    io:format("Process data: ~p ~n", [ Data]),
    Data.



blah. time for stress-test ;)
Tags: erlang, proxy, socket
Subscribe

  • Ubuntu Custom CD: a quick and dirty way

    A few notes on my practical experience of building custom ubuntu disks. I work here with Ubuntu Precise (12.04). But any other Ubuntu distro should…

  • OpenVAS 4.x/5.x from SVN source

    Didn't see any around. so here are my notes. Build instructions for Debian and ubuntu. Assuming pcap, libc, gcc are already installed. build…

  • Chunked decoding in python

    I haven't been able to find any short and quick method of decoding "chunked-encoding" encoded data in python without whacking 3rd party libraries, so…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments