Advertisement
fuxoft

Erlang webserver example

Jul 4th, 2014
607
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 2.90 KB | None | 0 0
  1. -module(webserver).
  2. -export([start/1, loop/1]).
  3.  
  4. -include("debug.hrl").
  5.  
  6. start(_) ->
  7.     Port = 8080,
  8.     {ok, Sock} = gen_tcp:listen(Port, [{active, false}, {packet, line}, {reuseaddr, true}]),
  9.     loop(Sock).
  10.  
  11. loop(Sock) ->
  12.     case gen_tcp:accept(Sock, 1000) of
  13.         {ok, ConnSock} ->
  14.             spawn_link(fun () -> handle(ConnSock) end);
  15.         {error, timeout} ->
  16.             socket_timeout;
  17.         Err ->
  18.             error({webserver_sock_accept,Err})
  19.     end,
  20.     receive
  21.         code_change ->
  22.             logger:log([webserver, code],{code_change}),
  23.             ?MODULE:loop(Sock);
  24.         Unknown ->
  25.             logger:log([critical,webserver],{unhandled_receive, Unknown}),
  26.             loop(Sock)
  27.     after 0 ->
  28.         loop(Sock)
  29.     end.
  30.  
  31. handle(Conn) ->
  32.     Timeout = 20000 + (erlang:crc32(pid_to_list(self())) band 8191),
  33.     Got = get_request(Conn),
  34.     % ?DEBUG("Got request: ~p", [Got]),
  35.     % muze byt {error,enotconn!}
  36.     IP = case inet:peername(Conn) of
  37.         {ok, {IPaddr, _Port}} ->
  38.             IPaddr;
  39.         _ ->
  40.             {69,69,69,69}
  41.     end,
  42.     flood_activity(IP, Got, 0),
  43.     {ok, {_Score, TextStatus}} = floodbot:status_of(IP),
  44.     case TextStatus of
  45.         ok ->
  46.             send_request_to_lua(Got);
  47.         flooding ->
  48.             self() ! {flooding, right_now}
  49.     end,
  50.     Reply = handle_loop(Conn, IP, Timeout, Got),
  51.     gen_tcp:send(Conn, create_response(Reply)),
  52.     gen_tcp:close(Conn),
  53.     exit(normal).
  54.  
  55. handle_loop(Conn, IP, Timeout, Got) ->
  56.     receive
  57.         {flooding,_FloodInfo} ->
  58.             "<h2>Flooding attempt detected from this address, sorry...<p>Please leave for a few minutes, otherwise you'll be kept locked out.</h2>";
  59.         {http_reply, Body} -> Body;
  60.         {flood_activity, Score} ->
  61.             flood_activity(IP, Got, Score),
  62.             handle_loop(Conn, IP, Timeout, Got);
  63.         Dunno ->
  64.             logger:log([socket, critical],{unhandled_receive, Dunno}),
  65.             exit(normal)
  66.     after Timeout ->
  67.         server:send_to(luaserver, {webserver, self(), connection_aborted}),
  68.         "IDLE"
  69.     end.
  70.  
  71. get_request(Conn) ->
  72.     RevParts = get_request(Conn, []),
  73.     lists:concat(lists:reverse(RevParts)).
  74.  
  75. get_request(Conn, RevParts) ->
  76.     Part = gen_tcp:recv(Conn, 0, 5000),
  77.     case Part of
  78.         {ok,"\r\n"} -> %konec requestu
  79.             RevParts;
  80.         {ok, Bytes} ->
  81.             get_request(Conn, [Bytes | RevParts]);
  82.         {error, _Err} ->
  83.             server:send_to(luaserver, {webserver, self(), connection_aborted}),
  84.             gen_tcp:close(Conn),
  85.             % logger:log([socket, debug], {socket_error, self(), Err}),
  86.             exit(normal);
  87.         Any ->
  88.             logger:log([socket,critical], {unknown_from_socket, Any}), %Really shouldn't happen
  89.             exit(normal)
  90.     end.
  91.  
  92. send_request_to_lua(String) ->
  93.     server:send_to(luaserver, {webserver, self(), new_connection, String}).
  94.  
  95. create_response(Str) ->
  96.     string_to_response(Str).
  97.  
  98. string_to_response(Str) ->
  99.     B = iolist_to_binary(Str),
  100.     iolist_to_binary(
  101.         io_lib:fwrite(
  102.             "HTTP/1.0 200 OK\nContent-Type: text/html\nAccess-Control-Allow-Origin: *\nContent-Length: ~p\n\n~s",
  103.             [size(B), B])).
  104.  
  105. flood_activity(IP, Request, Score) ->
  106.     server:send_to(floodbot, {self(), {flood_activity, Score, IP, Request}}).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement