blob: 10ac2b2536c4578275987081c298ed24570851ab [file] [log] [blame]
%%% Copyright (c) 2007- Facebook
%%% Distributed under the Thrift Software License
%%%
%%% See accompanying file LICENSE or visit the Thrift site at:
%%% http://developers.facebook.com/thrift/
-module(tErlServer).
-include("oop.hrl").
-include("thrift.hrl").
-include("transport/tTransportException.hrl").
-include("server/tErlServer.hrl").
-behavior(oop).
-export([attr/4, super/0, inspect/1]).
-export([new/6, new/5, new/4, effectful_serve/1, effectful_new_acceptor/1]).
%%%
%%% define attributes
%%% 'super' is required unless ?MODULE is a base class
%%%
?DEFINE_ATTR(super);
?DEFINE_ATTR(acceptor);
?DEFINE_ATTR(listenSocket);
?DEFINE_ATTR(port).
%%%
%%% behavior callbacks
%%%
%%% super() -> SuperModule = atom()
%%% | none
super() ->
tServer.
%%% inspect(This) -> string()
inspect(This) ->
?FORMAT_ATTR(acceptor) ++ ", " ++
?FORMAT_ATTR(listenSocket) ++ ", " ++
?FORMAT_ATTR(port).
%%%
%%% class methods
%%%
new(Port, Handler, Processor, ServerTransport, TransportFactory, ProtocolFactory) ->
Super = (super()):new(Handler, Processor, ServerTransport, TransportFactory, ProtocolFactory),
#?MODULE{super=Super, port=Port, listenSocket=nil, acceptor=nil}.
new(Port, Handler, Processor, ServerTransport) ->
new(Port, Handler, Processor, ServerTransport, nil, nil).
new(Port, Handler, Processor, ServerTransport, TransportFactory) ->
new(Port, Handler, Processor, ServerTransport, TransportFactory, nil).
% listenSocket, acceptor, port
effectful_serve(This) ->
Port = oop:get(This, port),
Options = [binary, {packet, 0}, {active, false}],
%% listen
case gen_tcp:listen(Port, Options) of
{ok, ListenSocket} ->
?INFO("thrift server listening on port ~p", [Port]),
This1 = oop:set(This, listenSocket, ListenSocket),
%% spawn acceptor
{_Acceptor, This2} = effectful_new_acceptor(This1),
{ok, This2};
{error, eaddrinuse} ->
?ERROR("thrift couldn't bind port ~p, address in use", [Port]),
{{error, eaddrinuse}, This} %% state before the accept
end.
effectful_new_acceptor(This) ->
ListenSocket = oop:get(This, listenSocket),
Processor = oop:get(This, processor), %% cpiro: generated processor, not the "actual" processor
Handler = oop:get(This, handler),
TF = oop:get(This, transportFactory),
PF = oop:get(This, protocolFactory),
tErlAcceptor = oop:get(This, serverTransport), %% cpiro: only supported ServerTransport
ServerPid = self(),
Acceptor = oop:start_new(tErlAcceptor, [ServerPid, TF, PF]),
?C3(Acceptor, accept, ListenSocket, Processor, Handler),
This1 = oop:set(This, acceptor, Acceptor),
{Acceptor, This1}.