Skip to content

Instantly share code, notes, and snippets.

@majimenezp
Created October 30, 2013 00:03
Show Gist options
  • Save majimenezp/7224925 to your computer and use it in GitHub Desktop.
Save majimenezp/7224925 to your computer and use it in GitHub Desktop.
Un proxy sencillo en Erlang en un solo archivo,no mas pa practicar este lenguaje
-module(nydus).
-export([test/0]).
-export([listener/1]).
-compile(debug_info).
test()->
listener(3333).
listener(Port) ->
spawn(fun () -> {ok, Sock} = gen_tcp:listen(Port, [inet,binary,{active, false}]),
mainLoop(Sock) end).
mainLoop(Sock)->
{ok, Conn} = gen_tcp:accept(Sock),
Handler = spawn(fun () -> handle(Conn) end),
gen_tcp:controlling_process(Conn, Handler),
mainLoop(Sock).
handle(Conn) ->
{ok, Bin} = do_recv(Conn, []),
if is_binary(Bin) ->
{ok,ReqPayload,RemoteHost,RemotePort}=create_Request(binary_to_list(Bin)),
{ok,SockExternalReq}=gen_tcp:connect(RemoteHost, RemotePort, [inet,
binary,
{packet,0},
{active,false},
{nodelay,true},
{send_timeout,200},
{recbuf,1024},
{send_timeout_close, true}
],2000),
case gen_tcp:send(SockExternalReq,list_to_binary(ReqPayload)) of
{error,timeout}->
io:format("timeout"),
gen_tcp:close(SockExternalReq),
gen_tcp:close(Conn);
{error,OtherSendError} ->
io:format("error: ~p",[OtherSendError]),
gen_tcp:close(SockExternalReq),
gen_tcp:close(Conn);
ok->
{ok,Response}=do_recvExternalResponse(SockExternalReq,Conn,[]),
gen_tcp:close(SockExternalReq),
gen_tcp:close(Conn),
_->
io:format("otro")
end;
true->
io:format("Info:~w ~n",[Bin]),
ok=gen_tcp:send(Conn,list_to_binary("")),
gen_tcp:close(Conn)
end,
ok.
create_Request(Payload)->
RequestLines=re:split(Payload,"\r\n",[{return,list}]),
RemoteHost=lists:nth(1,
re:split(
re:replace(
lists:nth(2,
re:split(
lists:nth(1,RequestLines)
," ",[{return,list}])
),
"http://","",[{return,list}])
,"/",[{return,list}])
),
RemoteFile=re:replace(
re:replace(
lists:nth(1,RequestLines),
"http://","",[{return,list}]),
RemoteHost,"",[{return,list}]),
%% get the server port
Port=get_Port(RemoteHost),
[_|NewReqLines]=RequestLines,
ReqPayload=[RemoteFile |NewReqLines],
{ok,string:join(ReqPayload,"\r\n"),RemoteHost,Port}.
get_Port(HostString)->
HostParts=re:split(HostString,":",[{return,list}]),
if length(HostParts)>1->
string:to_integer(lists:nth(2,HostParts));
true->
80
end.
do_recv(SockRcv, Bs) ->
case gen_tcp:recv(SockRcv, 0) of
{ok, B} ->
ReqTerminatorIsPresent=check_terminator(B),
Result=if ReqTerminatorIsPresent ->
{ok, B};
true->
do_recv(SockRcv, [Bs, B])
end,
Result;
{error, closed} ->
{ok, Bs}
end.
do_recvExternalResponse(SockExtResp,SockResp,Bs1)->
case gen_tcp:recv(SockExtResp,0,1000) of
{ok,Resp}->
gen_tcp:send(SockResp,Resp),
do_recvExternalResponse(SockExtResp,SockResp,[Bs1,Resp]);
{error,closed}->
{ok,list_to_binary(Bs1)};
{error,timeout}->
{ok,Bs1};
_->
io:format("~n ??? otra cosa.~n")
end.
check_terminator(ReqStr)->
%%io:format("longitud:~B~n",[LongPack]),
%%io:format("mensaje::~s~n",[ReqStr]),
ReqTerminator=re:run(binary_to_list(ReqStr),".*\r\n\r\n",[]),
case ReqTerminator of
nomatch->
false;
_->
true
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment