1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
16
%% $Id: httpd_socket.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
18
-module(httpd_socket).
20
listen/2, listen/3, accept/2, accept/3,
21
deliver/3, send/3, recv/4,
23
peername/2, resolve/1, config/1,
24
controlling_process/3,
27
-include("httpd.hrl").
29
-define(VMODULE,"SOCKET").
30
-include("httpd_verbosity.hrl").
32
-include_lib("kernel/include/inet.hrl").
34
%% start -> ok | {error,Reason}
37
case inet_db:start() of
40
{error,{already_started,_Pid}} ->
45
start({ssl,_SSLConfig}) ->
51
{error,{already_started,_}} ->
59
listen(SocketType,Port) ->
60
listen(SocketType,undefined,Port).
62
listen(ip_comm,Addr,Port) ->
63
?DEBUG("listening(ip_comm) to port ~p", [Port]),
64
Opt = sock_opt(Addr,[{backlog,128},{reuseaddr,true}]),
65
case gen_tcp:listen(Port,Opt) of
71
listen({ssl,SSLConfig},Addr,Port) ->
72
?DEBUG("listening(ssl) to port ~p"
73
"~n SSLConfig: ~p", [Port,SSLConfig]),
74
Opt = sock_opt(Addr,SSLConfig),
75
case ssl:listen(Port, Opt) of
83
sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
84
sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
86
%% -define(packet_type_http,true).
87
%% -define(packet_type_httph,true).
89
%% -ifdef(packet_type_http).
90
%% sock_opt(undefined,Opt) -> [{packet,http},{active,false}|Opt];
91
%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,http},{active,false}|Opt].
92
%% -elif(packet_type_httph).
93
%% sock_opt(undefined,Opt) -> [{packet,httph},{active,false}|Opt];
94
%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,httph},{active,false}|Opt].
96
%% sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
97
%% sock_opt(Addr,Opt) -> [{ip, Addr},{packet,0},{active,false}|Opt].
103
active_once(Type, Sock) ->
104
active(Type, Sock, once).
106
active(ip_comm, Sock, Active) ->
107
inet:setopts(Sock, [{active, Active}]);
108
active({ssl, _SSLConfig}, Sock, Active) ->
109
ssl:setopts(Sock, [{active, Active}]).
114
accept(A, B, infinity).
117
accept(ip_comm,ListenSocket, T) ->
118
?DEBUG("accept(ip_comm) on socket ~p", [ListenSocket]),
119
case gen_tcp:accept(ListenSocket, T) of
123
?vtrace("accept(ip_comm) failed for reason:"
124
"~n Error: ~p",[Error]),
127
accept({ssl,_SSLConfig},ListenSocket, T) ->
128
?DEBUG("accept(ssl) on socket ~p", [ListenSocket]),
129
case ssl:accept(ListenSocket, T) of
133
?vtrace("accept(ssl) failed for reason:"
134
"~n Error: ~p",[Error]),
139
%% controlling_process
141
controlling_process(ip_comm, Socket, Pid) ->
142
gen_tcp:controlling_process(Socket, Pid);
143
controlling_process({ssl, _}, Socket, Pid) ->
144
ssl:controlling_process(Socket, Pid).
149
deliver(SocketType, Socket, IOListOrBinary) ->
150
case send(SocketType, Socket, IOListOrBinary) of
152
% ?vlog("deliver failed for reason: einval"
153
% "~n SocketType: ~p"
156
% [SocketType, Socket, type(IOListOrBinary)]),
157
% (catch close(SocketType, Socket)),
160
?vlog("deliver(~p) failed for reason:"
161
"~n Reason: ~p",[SocketType,_Reason]),
162
(catch close(SocketType, Socket)),
168
% type(L) when list(L) ->
170
% type(B) when binary(B) ->
172
% case (catch binary_to_term(B)) of
174
% %% Oups, not a term, try list
175
% case (catch binary_to_list(B)) of
176
% %% Oups, not a list either, give up
187
% type(T) when tuple(T) ->
189
% type(I) when integer(I) ->
191
% type(F) when float(F) ->
193
% type(P) when pid(P) ->
195
% type(P) when port(P) ->
197
% type(R) when reference(R) ->
204
send(ip_comm,Socket,Data) ->
205
?DEBUG("send(ip_comm) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
206
gen_tcp:send(Socket,Data);
207
send({ssl,SSLConfig},Socket,Data) ->
208
?DEBUG("send(ssl) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
209
ssl:send(Socket, Data).
211
recv(ip_comm,Socket,Length,Timeout) ->
212
?DEBUG("recv(ip_comm) -> read from socket ~p",[Socket]),
213
gen_tcp:recv(Socket,Length,Timeout);
214
recv({ssl,SSLConfig},Socket,Length,Timeout) ->
215
?DEBUG("recv(ssl) -> read from socket ~p",[Socket]),
216
ssl:recv(Socket,Length,Timeout).
219
data_size(L) when list(L) ->
220
httpd_util:flatlength(L);
221
data_size(B) when binary(B) ->
230
peername(ip_comm, Socket) ->
231
case inet:peername(Socket) of
232
{ok,{{A,B,C,D},Port}} ->
233
PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
234
integer_to_list(C)++"."++integer_to_list(D),
235
?DEBUG("peername(ip_comm) on socket ~p: ~p",
236
[Socket,{Port,PeerName}]),
239
?vlog("failed getting peername:"
245
peername({ssl,_SSLConfig},Socket) ->
246
case ssl:peername(Socket) of
247
{ok,{{A,B,C,D},Port}} ->
248
PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
249
integer_to_list(C)++"."++integer_to_list(D),
250
?DEBUG("peername(ssl) on socket ~p: ~p",
251
[Socket, {Port,PeerName}]),
260
{ok,Name} = inet:gethostname(),
265
close(ip_comm,Socket) ->
267
case (catch gen_tcp:close(Socket)) of
269
{error,Reason} -> {error,Reason};
270
{'EXIT',{noproc,_}} -> {error,closed};
271
{'EXIT',Reason} -> {error,Reason};
272
Otherwise -> {error,Otherwise}
274
?vtrace("close(ip_comm) result: ~p",[Res]),
276
close({ssl,_SSLConfig},Socket) ->
278
case (catch ssl:close(Socket)) of
280
{error,Reason} -> {error,Reason};
281
{'EXIT',{noproc,_}} -> {error,closed};
282
{'EXIT',Reason} -> {error,Reason};
283
Otherwise -> {error,Otherwise}
285
?vtrace("close(ssl) result: ~p",[Res]),
288
%% config (debug: {certfile, "/var/tmp/server_root/conf/ssl_server.pem"})
291
case httpd_util:lookup(ConfigDB,com_type,ip_comm) of
293
case ssl_certificate_file(ConfigDB) of
296
?NICE("Directive SSLCertificateFile "
297
"not found in the config file")};
298
SSLCertificateFile ->
301
ssl_certificate_key_file(ConfigDB)++
302
ssl_verify_client(ConfigDB)++
303
ssl_ciphers(ConfigDB)++
304
ssl_password(ConfigDB)++
305
ssl_verify_depth(ConfigDB)++
306
ssl_ca_certificate_file(ConfigDB)}
312
ssl_certificate_file(ConfigDB) ->
313
case httpd_util:lookup(ConfigDB,ssl_certificate_file) of
316
SSLCertificateFile ->
317
[{certfile,SSLCertificateFile}]
320
ssl_certificate_key_file(ConfigDB) ->
321
case httpd_util:lookup(ConfigDB,ssl_certificate_key_file) of
324
SSLCertificateKeyFile ->
325
[{keyfile,SSLCertificateKeyFile}]
328
ssl_verify_client(ConfigDB) ->
329
case httpd_util:lookup(ConfigDB,ssl_verify_client) of
333
[{verify,SSLVerifyClient}]
336
ssl_ciphers(ConfigDB) ->
337
case httpd_util:lookup(ConfigDB,ssl_ciphers) of
344
ssl_password(ConfigDB) ->
345
case httpd_util:lookup(ConfigDB,ssl_password_callback_module) of
349
case httpd_util:lookup(ConfigDB, ssl_password_callback_function) of
353
case catch apply(Module, Function, []) of
354
Password when list(Password) ->
355
[{password, Password}];
357
error_report(ssl_password,Module,Function,Error),
363
ssl_verify_depth(ConfigDB) ->
364
case httpd_util:lookup(ConfigDB, ssl_verify_client_depth) of
371
ssl_ca_certificate_file(ConfigDB) ->
372
case httpd_util:lookup(ConfigDB, ssl_ca_certificate_file) of
380
error_report(Where,M,F,Error) ->
381
error_logger:error_report([{?MODULE, Where}, {apply, {M, F, []}}, Error]).