| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | %% | 
 | 2 | %% Licensed to the Apache Software Foundation (ASF) under one | 
 | 3 | %% or more contributor license agreements. See the NOTICE file | 
 | 4 | %% distributed with this work for additional information | 
 | 5 | %% regarding copyright ownership. The ASF licenses this file | 
 | 6 | %% to you under the Apache License, Version 2.0 (the | 
 | 7 | %% "License"); you may not use this file except in compliance | 
 | 8 | %% with the License. You may obtain a copy of the License at | 
 | 9 | %% | 
 | 10 | %%   http://www.apache.org/licenses/LICENSE-2.0 | 
 | 11 | %% | 
 | 12 | %% Unless required by applicable law or agreed to in writing, | 
 | 13 | %% software distributed under the License is distributed on an | 
 | 14 | %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
 | 15 | %% KIND, either express or implied. See the License for the | 
 | 16 | %% specific language governing permissions and limitations | 
 | 17 | %% under the License. | 
 | 18 | %% | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 19 |  | 
| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 20 | -module(thrift_socket_server). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 21 |  | 
 | 22 | -behaviour(gen_server). | 
 | 23 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 24 | -include("thrift_constants.hrl"). | 
 | 25 |  | 
 | 26 | -export([start/1, stop/1]). | 
 | 27 | -export([ | 
 | 28 |     init/1, | 
 | 29 |     handle_call/3, | 
 | 30 |     handle_cast/2, | 
 | 31 |     terminate/2, | 
 | 32 |     code_change/3, | 
 | 33 |     handle_info/2 | 
 | 34 | ]). | 
 | 35 | -export([acceptor_loop/1]). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 36 |  | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 37 | -ifdef(TEST). | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 38 | -export([parse_options/1]). | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 39 | -endif. | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 40 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 41 | -type protocol() :: | 
 | 42 |     compact | 
 | 43 |     | {compact, term()} | 
 | 44 |     | json | 
 | 45 |     | {json, term()} | 
 | 46 |     | binary | 
 | 47 |     | {binary | term()} | 
 | 48 |     | {custom, module(), term()}. | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 49 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 50 | -type socket_opts() :: [inet:inet_backend() | gen_tcp:listen_option()]. | 
 | 51 | -type ssl_opts() :: [ssl:tls_server_option()]. | 
 | 52 |  | 
 | 53 | -record(thrift_socket_server, { | 
 | 54 |     port :: inet:port_number(), | 
 | 55 |     service :: thrift_multiplexed_map_wrapper:service_handler_map(), | 
 | 56 |     handler :: thrift_multiplexed_map_wrapper:service_handler_map(), | 
 | 57 |     acceptors_left :: non_neg_integer(), | 
 | 58 |     listen :: gen_tcp:socket(), | 
 | 59 |     acceptor :: undefined | pid(), | 
 | 60 |     socket_opts :: socket_opts(), | 
 | 61 |     protocol :: protocol(), | 
 | 62 |     framed :: boolean(), | 
 | 63 |     ssltransport :: boolean(), | 
 | 64 |     ssloptions :: ssl_opts() | 
 | 65 | }). | 
 | 66 |  | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 67 | start(Options) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 68 |     start_server(parse_options(Options)). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 69 |  | 
 | 70 | stop(Name) when is_atom(Name) -> | 
 | 71 |     gen_server:cast(Name, stop); | 
 | 72 | stop(Pid) when is_pid(Pid) -> | 
 | 73 |     gen_server:cast(Pid, stop); | 
 | 74 | stop({local, Name}) -> | 
 | 75 |     stop(Name); | 
 | 76 | stop({global, Name}) -> | 
 | 77 |     stop(Name); | 
 | 78 | stop(Options) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 79 |     #{name := Name} = parse_options(Options), | 
 | 80 |     stop(Name). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 81 |  | 
 | 82 | %% Internal API | 
 | 83 |  | 
 | 84 | parse_options(Options) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 85 |     parse_options(Options, #{}). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 86 |  | 
 | 87 | parse_options([], State) -> | 
 | 88 |     State; | 
 | 89 | parse_options([{name, L} | Rest], State) when is_list(L) -> | 
 | 90 |     Name = {local, list_to_atom(L)}, | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 91 |     parse_options(Rest, State#{name => Name}); | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 92 | parse_options([{name, A} | Rest], State) when is_atom(A) -> | 
 | 93 |     Name = {local, A}, | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 94 |     parse_options(Rest, State#{name => Name}); | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 95 | parse_options([{name, Name} | Rest], State) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 96 |     parse_options(Rest, State#{name => Name}); | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 97 | parse_options([{port, L} | Rest], State) when is_list(L) -> | 
 | 98 |     Port = list_to_integer(L), | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 99 |     parse_options(Rest, State#{port => Port}); | 
 | 100 | parse_options([{port, Port} | Rest], State) when is_integer(Port), Port >= 0, Port =< 65535 -> | 
 | 101 |     parse_options(Rest, State#{port => Port}); | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 102 | parse_options([{ip, Ip} | Rest], State) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 103 |     case Ip of | 
 | 104 |         any -> | 
 | 105 |             parse_options(Rest, State); | 
 | 106 |         Ip when is_tuple(Ip) -> | 
 | 107 |             parse_options(Rest, State#{ip => Ip}); | 
 | 108 |         Ip when is_list(Ip) -> | 
 | 109 |             {ok, IpTuple} = inet_parse:address(Ip), | 
 | 110 |             parse_options(Rest, State#{ip => IpTuple}) | 
 | 111 |     end; | 
| David Reiss | b7c8802 | 2008-06-11 01:00:20 +0000 | [diff] [blame] | 112 | parse_options([{socket_opts, L} | Rest], State) when is_list(L), length(L) > 0 -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 113 |     parse_options(Rest, State#{socket_opts => L}); | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 114 | parse_options([{handler, []} | _Rest], _State) -> | 
 | 115 |     throw("At least an error handler must be defined."); | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 116 | parse_options([{handler, ServiceHandlerPropertyList} | Rest], State) when | 
 | 117 |     is_list(ServiceHandlerPropertyList) | 
 | 118 | -> | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 119 |     ServiceHandlerMap = | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 120 |         case maps:get(handler, State, undefined) of | 
 | 121 |             undefined -> | 
 | 122 |                 lists:foldl( | 
 | 123 |                     fun | 
 | 124 |                         ({ServiceName, ServiceHandler}, Acc) when | 
 | 125 |                             is_list(ServiceName), is_atom(ServiceHandler) | 
 | 126 |                         -> | 
 | 127 |                             thrift_multiplexed_map_wrapper:store(ServiceName, ServiceHandler, Acc); | 
 | 128 |                         (_, _Acc) -> | 
 | 129 |                             throw( | 
 | 130 |                                 "The handler option is not properly configured for multiplexed services. It should be a kind of [{\"error_handler\", Module::atom()}, {SericeName::list(), Module::atom()}, ...]" | 
 | 131 |                             ) | 
 | 132 |                     end, | 
 | 133 |                     thrift_multiplexed_map_wrapper:new(), | 
 | 134 |                     ServiceHandlerPropertyList | 
 | 135 |                 ); | 
 | 136 |             _ -> | 
 | 137 |                 throw("Error while parsing the handler option.") | 
 | 138 |         end, | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 139 |     case thrift_multiplexed_map_wrapper:find(?MULTIPLEXED_ERROR_HANDLER_KEY, ServiceHandlerMap) of | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 140 |         {ok, _ErrorHandler} -> | 
 | 141 |             parse_options(Rest, State#{handler => ServiceHandlerMap}); | 
 | 142 |         error -> | 
 | 143 |             throw( | 
 | 144 |                 "The handler option is not properly configured for multiplexed services. It should be a kind of [{\"error_handler\", Module::atom()}, {SericeName::list(), Module::atom()}, ...]" | 
 | 145 |             ) | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 146 |     end; | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 147 | parse_options([{handler, Handler} | Rest], State) when | 
 | 148 |     not is_map_key(handler, State), is_atom(Handler) | 
 | 149 | -> | 
 | 150 |     parse_options(Rest, State#{handler => Handler}); | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 151 | parse_options([{service, []} | _Rest], _State) -> | 
 | 152 |     throw("At least one service module must be defined."); | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 153 | parse_options([{service, ServiceModulePropertyList} | Rest], State) when | 
 | 154 |     is_list(ServiceModulePropertyList) | 
 | 155 | -> | 
| David Robakowski | ae971ce | 2013-08-02 12:16:00 +0200 | [diff] [blame] | 156 |     ServiceModuleMap = | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 157 |         case maps:get(service, State, undefined) of | 
 | 158 |             undefined -> | 
 | 159 |                 lists:foldl( | 
 | 160 |                     fun | 
 | 161 |                         ({ServiceName, ServiceModule}, Acc) when | 
 | 162 |                             is_list(ServiceName), is_atom(ServiceModule) | 
 | 163 |                         -> | 
 | 164 |                             thrift_multiplexed_map_wrapper:store(ServiceName, ServiceModule, Acc); | 
 | 165 |                         (_, _Acc) -> | 
 | 166 |                             throw( | 
 | 167 |                                 "The service option is not properly configured for multiplexed services. It should be a kind of [{SericeName::list(), ServiceModule::atom()}, ...]" | 
 | 168 |                             ) | 
 | 169 |                     end, | 
 | 170 |                     thrift_multiplexed_map_wrapper:new(), | 
 | 171 |                     ServiceModulePropertyList | 
 | 172 |                 ); | 
 | 173 |             _ -> | 
 | 174 |                 throw("Error while parsing the service option.") | 
 | 175 |         end, | 
 | 176 |     parse_options(Rest, State#{service => ServiceModuleMap}); | 
 | 177 | parse_options([{service, Service} | Rest], State) when | 
 | 178 |     not is_map_key(service, State), is_atom(Service) | 
 | 179 | -> | 
 | 180 |     parse_options(Rest, State#{service => Service}); | 
 | 181 | parse_options([{max, Max} | Rest], State) when is_integer(Max), Max > 0 -> | 
 | 182 |     parse_options(Rest, State#{max => Max}); | 
| Nobuaki Sukegawa | b31f090 | 2015-11-01 17:00:34 +0900 | [diff] [blame] | 183 | parse_options([{protocol, Proto} | Rest], State) when is_atom(Proto) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 184 |     parse_options(Rest, State#{protocol => Proto}); | 
| David Reiss | b42361c | 2009-09-09 17:18:57 +0000 | [diff] [blame] | 185 | parse_options([{framed, Framed} | Rest], State) when is_boolean(Framed) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 186 |     parse_options(Rest, State#{framed => Framed}); | 
| David Robakowski | a7d6a97 | 2013-08-07 05:51:00 +0200 | [diff] [blame] | 187 | parse_options([{ssltransport, SSLTransport} | Rest], State) when is_boolean(SSLTransport) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 188 |     parse_options(Rest, State#{ssltransport => SSLTransport}); | 
| David Robakowski | a7d6a97 | 2013-08-07 05:51:00 +0200 | [diff] [blame] | 189 | parse_options([{ssloptions, SSLOptions} | Rest], State) when is_list(SSLOptions) -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 190 |     parse_options(Rest, State#{ssloptions => SSLOptions}). | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 191 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 192 | start_server(Options = #{name := Name}) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 193 |     case Name of | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 194 |         undefined -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 195 |             gen_server:start_link(?MODULE, Options, []); | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 196 |         _ -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 197 |             gen_server:start_link(Name, ?MODULE, Options, []) | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 198 |     end. | 
 | 199 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 200 | init(State = #{port := Port}) -> | 
| David Reiss | d74b023 | 2008-06-11 01:02:55 +0000 | [diff] [blame] | 201 |     process_flag(trap_exit, true), | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 202 |     BaseOpts = [ | 
 | 203 |         binary, | 
 | 204 |         {reuseaddr, true}, | 
 | 205 |         {packet, 0}, | 
 | 206 |         {backlog, 4096}, | 
 | 207 |         {recbuf, 8192}, | 
 | 208 |         {active, false} | 
 | 209 |     ], | 
 | 210 |     Opts = | 
 | 211 |         case maps:get(ip, State, undefined) of | 
 | 212 |             undefined -> | 
 | 213 |                 BaseOpts; | 
 | 214 |             Ip -> | 
 | 215 |                 [{ip, Ip} | BaseOpts] | 
 | 216 |         end, | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 217 |     case gen_tcp:listen(Port, Opts) of | 
 | 218 |         {ok, Listen} -> | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 219 |             {ok, ListenPort} = inet:port(Listen), | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 220 |             {ok, | 
 | 221 |                 new_acceptor(#thrift_socket_server{ | 
 | 222 |                     acceptors_left = maps:get(max, State, 2048), | 
 | 223 |                     listen = Listen, | 
 | 224 |                     port = ListenPort, | 
 | 225 |                     service = maps:get(service, State), | 
 | 226 |                     handler = maps:get(handler, State), | 
 | 227 |                     socket_opts = maps:get(socket_opts, State, [{recv_timeout, 500}]), | 
 | 228 |                     framed = maps:get(framed, State, false), | 
 | 229 |                     protocol = maps:get(protocol, State, binary), | 
 | 230 |                     ssltransport = maps:get(ssltransport, State, false), | 
 | 231 |                     ssloptions = maps:get(ssloptions, State, []) | 
 | 232 |                 })}; | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 233 |         {error, Reason} -> | 
 | 234 |             {stop, Reason} | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 235 |     end. | 
 | 236 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 237 | new_acceptor(State = #thrift_socket_server{acceptors_left = 0}) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 238 |     error_logger:error_msg("Not accepting new connections"), | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 239 |     State#thrift_socket_server{acceptor = undefined}; | 
 | 240 | new_acceptor( | 
 | 241 |     State = #thrift_socket_server{ | 
 | 242 |         listen = Listen, | 
 | 243 |         service = Service, | 
 | 244 |         handler = Handler, | 
 | 245 |         socket_opts = Opts, | 
 | 246 |         framed = Framed, | 
 | 247 |         protocol = Proto, | 
 | 248 |         ssltransport = SslTransport, | 
 | 249 |         ssloptions = SslOptions | 
 | 250 |     } | 
 | 251 | ) -> | 
 | 252 |     Pid = proc_lib:spawn_link( | 
 | 253 |         ?MODULE, | 
 | 254 |         acceptor_loop, | 
 | 255 |         [{self(), Listen, Service, Handler, Opts, Framed, SslTransport, SslOptions, Proto}] | 
 | 256 |     ), | 
 | 257 |     State#thrift_socket_server{acceptor = Pid}. | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 258 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 259 | acceptor_loop( | 
 | 260 |     {Server, Listen, Service, Handler, SocketOpts, Framed, SslTransport, SslOptions, Proto} | 
 | 261 | ) when | 
 | 262 |     is_pid(Server), is_list(SocketOpts) | 
 | 263 | -> | 
 | 264 |     % infinite timeout | 
 | 265 |     case catch gen_tcp:accept(Listen) of | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 266 |         {ok, Socket} -> | 
 | 267 |             gen_server:cast(Server, {accepted, self()}), | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 268 |             ProtoGen = fun() -> | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 269 |                 {ok, SocketTransport} = | 
 | 270 |                     case SslTransport of | 
 | 271 |                         true -> thrift_sslsocket_transport:new(Socket, SocketOpts, SslOptions); | 
 | 272 |                         false -> thrift_socket_transport:new(Socket, SocketOpts) | 
 | 273 |                     end, | 
 | 274 |                 {ok, Transport} = | 
 | 275 |                     case Framed of | 
 | 276 |                         true -> thrift_framed_transport:new(SocketTransport); | 
 | 277 |                         false -> thrift_buffered_transport:new(SocketTransport) | 
 | 278 |                     end, | 
 | 279 |                 {ok, Protocol} = | 
 | 280 |                     case Proto of | 
 | 281 |                         compact -> | 
 | 282 |                             thrift_compact_protocol:new(Transport); | 
 | 283 |                         {compact, Options} -> | 
 | 284 |                             thrift_compact_protocol:new(Transport, Options); | 
 | 285 |                         json -> | 
 | 286 |                             thrift_json_protocol:new(Transport); | 
 | 287 |                         {json, Options} -> | 
 | 288 |                             thrift_json_protocol:new(Transport, Options); | 
 | 289 |                         binary -> | 
 | 290 |                             thrift_binary_protocol:new(Transport); | 
 | 291 |                         {binary, Options} -> | 
 | 292 |                             thrift_binary_protocol:new(Transport, Options); | 
 | 293 |                         {custom, Module, Options} -> | 
 | 294 |                             case erlang:function_exported(Module, new, 2) of | 
 | 295 |                                 true -> Module:new(Transport, Options); | 
 | 296 |                                 false -> throw("Could not instantiate custom protocol") | 
 | 297 |                             end | 
 | 298 |                     end, | 
 | 299 |                 {ok, Protocol} | 
 | 300 |             end, | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 301 |             thrift_processor:init({Server, ProtoGen, Service, Handler}); | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 302 |         {error, closed} -> | 
 | 303 |             exit({error, closed}); | 
 | 304 |         Other -> | 
 | 305 |             error_logger:error_report( | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 306 |                 [ | 
 | 307 |                     {application, thrift}, | 
 | 308 |                     "Accept failed error", | 
 | 309 |                     lists:flatten(io_lib:format("~p", [Other])) | 
 | 310 |                 ] | 
 | 311 |             ), | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 312 |             exit({error, accept_failed}) | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 313 |     end. | 
 | 314 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 315 | handle_call({get, port}, _From, State = #thrift_socket_server{port = Port}) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 316 |     {reply, Port, State}; | 
 | 317 | handle_call(_Message, _From, State) -> | 
 | 318 |     Res = error, | 
 | 319 |     {reply, Res, State}. | 
 | 320 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 321 | handle_cast( | 
 | 322 |     {accepted, Pid}, | 
 | 323 |     State = #thrift_socket_server{acceptor = Pid, acceptors_left = Max} | 
 | 324 | ) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 325 |     % io:format("accepted ~p~n", [Pid]), | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 326 |     State1 = State#thrift_socket_server{acceptors_left = Max - 1}, | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 327 |     {noreply, new_acceptor(State1)}; | 
 | 328 | handle_cast(stop, State) -> | 
 | 329 |     {stop, normal, State}. | 
 | 330 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 331 | terminate(Reason, #thrift_socket_server{listen = Listen}) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 332 |     gen_tcp:close(Listen), | 
| Sergey Elin | ce32ed7 | 2019-05-05 20:14:43 +0300 | [diff] [blame] | 333 |     case Reason of | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 334 |         normal -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 335 |             ok; | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 336 |         shutdown -> | 
 | 337 |             ok; | 
 | 338 |         _ -> | 
 | 339 |             {backtrace, Bt} = erlang:process_info(self(), backtrace), | 
 | 340 |             error_logger:error_report({?MODULE, ?LINE, {child_error, Reason, Bt}}) | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 341 |     end. | 
 | 342 |  | 
 | 343 | code_change(_OldVsn, State, _Extra) -> | 
 | 344 |     State. | 
 | 345 |  | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 346 | handle_info( | 
 | 347 |     {'EXIT', Pid, normal}, | 
 | 348 |     State = #thrift_socket_server{acceptor = Pid} | 
 | 349 | ) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 350 |     {noreply, new_acceptor(State)}; | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 351 | handle_info( | 
 | 352 |     {'EXIT', Pid, Reason}, | 
 | 353 |     State = #thrift_socket_server{acceptor = Pid} | 
 | 354 | ) -> | 
 | 355 |     error_logger:error_report({?MODULE, ?LINE, {acceptor_error, Reason}}), | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 356 |     timer:sleep(100), | 
 | 357 |     {noreply, new_acceptor(State)}; | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 358 | handle_info( | 
 | 359 |     {'EXIT', _LoopPid, Reason}, | 
 | 360 |     State = #thrift_socket_server{acceptor = Pid, acceptors_left = AcceptorsLeft} | 
 | 361 | ) -> | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 362 |     case Reason of | 
| David Reiss | 1a2f218 | 2008-06-11 01:14:01 +0000 | [diff] [blame] | 363 |         normal -> ok; | 
| David Reiss | 4cf5a6a | 2008-06-11 01:00:59 +0000 | [diff] [blame] | 364 |         shutdown -> ok; | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 365 |         _ -> error_logger:error_report({?MODULE, ?LINE, {child_error, Reason}}) | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 366 |     end, | 
| Sergei Elin | 4576409 | 2022-09-23 23:21:31 +0300 | [diff] [blame] | 367 |     State1 = State#thrift_socket_server{acceptors_left = AcceptorsLeft + 1}, | 
 | 368 |     State2 = | 
 | 369 |         case Pid of | 
 | 370 |             undefined -> new_acceptor(State1); | 
 | 371 |             _ -> State1 | 
 | 372 |         end, | 
| David Reiss | 8086231 | 2008-06-11 00:59:55 +0000 | [diff] [blame] | 373 |     {noreply, State2}; | 
 | 374 | handle_info(Info, State) -> | 
 | 375 |     error_logger:info_report([{'INFO', Info}, {'State', State}]), | 
 | 376 |     {noreply, State}. |