2
%% <year>2005-2007</year>
3
%% <holder>Ericsson AB, All Rights Reserved</holder>
6
%% The contents of this file are subject to the Erlang Public License,
7
%% Version 1.1, (the "License"); you may not use this file except in
8
%% compliance with the License. You should have received a copy of the
9
%% Erlang Public License along with this software. If not, it can be
10
%% retrieved online at http://www.erlang.org/.
12
%% Software distributed under the License is distributed on an "AS IS"
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
%% the License for the specific language governing rights and limitations
17
%% The Initial Developer of the Original Code is Ericsson AB.
21
%%% Description: tcp listen and accept-loop
23
-module(ssh_tcp_wrap).
25
-export([spawn_server/3, server/4]).
26
-export([server_init/4, server_loop/3, accept_loop/4]). %% helper
28
-define(ACCEPT_TIMEOUT, 10000).
30
%% Spawn the server loop
31
spawn_server(Port, Opts, Fun) ->
32
Pid = spawn(?MODULE, server_init, [self(),Port,Opts,Fun]),
33
Ref = erlang:monitor(process, Pid),
35
{'DOWN', Ref, _, _, Reason} ->
38
erlang:demonitor(Ref),
42
server_init(Starter, Port, Opts, Fun) ->
43
case gen_tcp:listen(Port, Opts) of
46
case inet:sockname(Listen) of
48
Starter ! {self(), {ok,self(),Port1}},
49
server_loop(self(), Listen, Fun);
51
gen_tcp:close(Listen),
52
Starter ! {self(), Error}
55
Starter ! {self(), {ok,self(),Port}},
56
server_loop(self(), Listen, Fun)
60
"Failed to listen on port: ~p opts:~p: rsn:~p~n",
62
Starter ! {self(), Error}
66
%% Run the server loop
67
server(Port, Opts, Fun, From) ->
68
case gen_tcp:listen(Port, Opts) of
71
server_loop(self(), Listen, Fun);
74
"Failed to listen on port: ~p opts:~p: rsn:~p~n",
79
server_loop(User, Listen, Fun) ->
81
?MODULE:accept_loop(User, erlang:monitor(process,User),
84
Ref = erlang:monitor(process, Pid),
86
{'DOWN', Ref, _, _, _Reason} ->
87
?MODULE:server_loop(User, Listen, Fun);
93
erlang:demonitor(Ref),
94
?MODULE:server_loop(User, Listen, Fun)
97
accept_loop(User, Ref, Listen, Fun) ->
98
%% Timeout makes it possible to replace this module
99
%% once every ?ACCEPT_TIMEOUT milliseconds
100
case gen_tcp:accept(Listen, ?ACCEPT_TIMEOUT) of
102
%% poll if 'User' is still alive
104
{'DOWN', Ref, _, _, Reason} ->
112
%% poll if 'User' is still alive
114
{'DOWN', Ref, _, _, Reason} ->
117
?MODULE:accept_loop(User, Ref, Listen, Fun)
120
Listen ! {self(), stop};
122
Listen ! {self(), Error}