aboutsummaryrefslogblamecommitdiffstats
path: root/lib/dialyzer/test/r9c_SUITE_data/src/inets/httpd_socket.erl
blob: fff28b7ac445abc68ac653cbaee28dc7a45eb740 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11


                                                                    
  






                                                                           
  


                                                                         
  




                                                                  
                                   






































































































































                                                                             
                                              



                                                          
                                              







                           
               









                                                       
 


















                              
 















                                                                              
                            





























                                                                         
                                                    














                                              
         









                                                    
         







































































































                                                                               
%% ``Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
%%     $Id: httpd_socket.erl,v 1.1 2008/12/17 09:53:34 mikpe Exp $
%%
-module(httpd_socket).
-export([start/1,
	 listen/2, listen/3, accept/2, accept/3,
	 deliver/3, send/3, recv/4,
	 close/2,
	 peername/2, resolve/1, config/1,
	 controlling_process/3,
	 active_once/2]).

-include("httpd.hrl").

-define(VMODULE,"SOCKET").
-include("httpd_verbosity.hrl").

-include_lib("kernel/include/inet.hrl").

%% start -> ok | {error,Reason}

start(ip_comm) ->
    case inet_db:start() of
	{ok,_Pid} ->
	    ok;
	{error,{already_started,_Pid}} ->
	    ok;
	Error ->
	    Error
    end;
start({ssl,_SSLConfig}) ->
    case ssl:start() of
	ok ->
	    ok;
	{ok, _} ->
	    ok;
	{error,{already_started,_}} ->
	    ok;
	Error ->
	    Error
    end.

%% listen

listen(SocketType,Port) ->
    listen(SocketType,undefined,Port).

listen(ip_comm,Addr,Port) ->
    ?DEBUG("listening(ip_comm) to port ~p", [Port]),
    Opt = sock_opt(Addr,[{backlog,128},{reuseaddr,true}]),
    case gen_tcp:listen(Port,Opt) of
	{ok,ListenSocket} ->
	    ListenSocket;
	Error ->
	    Error
    end;
listen({ssl,SSLConfig},Addr,Port) ->
    ?DEBUG("listening(ssl) to port ~p"
           "~n   SSLConfig: ~p", [Port,SSLConfig]),
    Opt = sock_opt(Addr,SSLConfig),
    case ssl:listen(Port, Opt) of
	{ok,ListenSocket} ->
	    ListenSocket;
	Error ->
	    Error
    end.


sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
sock_opt(Addr,Opt)      -> [{ip, Addr},{packet,0},{active,false}|Opt].

%% -define(packet_type_http,true).
%% -define(packet_type_httph,true).

%% -ifdef(packet_type_http).
%% sock_opt(undefined,Opt) -> [{packet,http},{active,false}|Opt];
%% sock_opt(Addr,Opt)      -> [{ip, Addr},{packet,http},{active,false}|Opt].
%% -elif(packet_type_httph).
%% sock_opt(undefined,Opt) -> [{packet,httph},{active,false}|Opt];
%% sock_opt(Addr,Opt)      -> [{ip, Addr},{packet,httph},{active,false}|Opt].
%% -else.
%% sock_opt(undefined,Opt) -> [{packet,0},{active,false}|Opt];
%% sock_opt(Addr,Opt)      -> [{ip, Addr},{packet,0},{active,false}|Opt].
%% -endif.


%% active_once

active_once(Type, Sock) ->
    active(Type, Sock, once).

active(ip_comm, Sock, Active) ->
    inet:setopts(Sock, [{active, Active}]);
active({ssl, _SSLConfig}, Sock, Active) ->
    ssl:setopts(Sock, [{active, Active}]).

%% accept

accept(A, B) ->
    accept(A, B, infinity).


accept(ip_comm,ListenSocket, T) ->
    ?DEBUG("accept(ip_comm) on socket ~p", [ListenSocket]),
    case gen_tcp:accept(ListenSocket, T) of
	{ok,Socket} ->
	    Socket;
	Error ->
	    ?vtrace("accept(ip_comm) failed for reason:"
		    "~n   Error: ~p",[Error]),
	    Error
    end;
accept({ssl,_SSLConfig},ListenSocket, T) ->
    ?DEBUG("accept(ssl) on socket ~p", [ListenSocket]),
    case ssl:accept(ListenSocket, T) of
	{ok,Socket} ->
	    Socket;
	Error ->
	    ?vtrace("accept(ssl) failed for reason:"
		    "~n   Error: ~p",[Error]),
	    Error
    end.


%% controlling_process

controlling_process(ip_comm, Socket, Pid) ->
    gen_tcp:controlling_process(Socket, Pid);
controlling_process({ssl, _}, Socket, Pid) ->
    ssl:controlling_process(Socket, Pid).


%% deliver

deliver(SocketType, Socket, IOListOrBinary)  ->
    case send(SocketType, Socket, IOListOrBinary) of
% 	{error, einval} ->
% 	    ?vlog("deliver failed for reason: einval"
% 		  "~n   SocketType: ~p"
% 		  "~n   Socket:     ~p"
% 		  "~n   Data:       ~p",
% 		  [SocketType, Socket, type(IOListOrBinary)]),
% 	    (catch close(SocketType, Socket)),
% 	    socket_closed;
	{error, _Reason} ->
	    ?vlog("deliver(~p) failed for reason:"
		  "~n   Reason: ~p",[SocketType,_Reason]),
	    (catch close(SocketType, Socket)),
	    socket_closed;
	_ ->
	    ok
    end.

% type(L) when list(L) ->
%     {list, L};
% type(B) when binary(B) ->
%     Decoded =
% 	case (catch binary_to_term(B)) of
% 	    {'EXIT', _} ->
% 		%% Oups, not a term, try list
% 		case (catch binary_to_list(B)) of
% 		    %% Oups, not a list either, give up
% 		    {'EXIT', _} ->
% 			{size, size(B)};
% 		    L ->
% 		    {list, L}
% 		end;

% 	    T ->
% 		{term, T}
% 	end,
%     {binary, Decoded};
% type(T) when tuple(T) ->
%     {tuple, T};
% type(I) when integer(I) ->
%     {integer, I};
% type(F) when float(F) ->
%     {float, F};
% type(P) when pid(P) ->
%     {pid, P};
% type(P) when port(P) ->
%     {port, P};
% type(R) when reference(R) ->
%     {reference, R};
% type(T) ->
%     {term, T}.



send(ip_comm,Socket,Data) ->
    ?DEBUG("send(ip_comm) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
    gen_tcp:send(Socket,Data);
send({ssl,SSLConfig},Socket,Data) ->
    ?DEBUG("send(ssl) -> ~p bytes on socket ~p",[data_size(Data),Socket]),
    ssl:send(Socket, Data).

recv(ip_comm,Socket,Length,Timeout) ->
    ?DEBUG("recv(ip_comm) -> read from socket ~p",[Socket]),
    gen_tcp:recv(Socket,Length,Timeout);
recv({ssl,SSLConfig},Socket,Length,Timeout) ->
    ?DEBUG("recv(ssl) -> read from socket ~p",[Socket]),
    ssl:recv(Socket,Length,Timeout).

-ifdef(inets_debug).
data_size(L) when list(L) ->
    httpd_util:flatlength(L);
data_size(B) when binary(B) ->
    size(B);
data_size(O) ->
    {unknown_size,O}.
-endif.


%% peername

peername(ip_comm, Socket) ->
    case inet:peername(Socket) of
	{ok,{{A,B,C,D},Port}} ->
	    PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
		integer_to_list(C)++"."++integer_to_list(D),
	    ?DEBUG("peername(ip_comm) on socket ~p: ~p",
		   [Socket,{Port,PeerName}]),
	    {Port,PeerName};
	{error,Reason} ->
	    ?vlog("failed getting peername:"
		  "~n   Reason: ~p"
		  "~n   Socket: ~p",
		  [Reason,Socket]),
	    {-1,"unknown"}
    end;
peername({ssl,_SSLConfig},Socket) ->
    case ssl:peername(Socket) of
	{ok,{{A,B,C,D},Port}} ->
	    PeerName = integer_to_list(A)++"."++integer_to_list(B)++"."++
		integer_to_list(C)++"."++integer_to_list(D),
	    ?DEBUG("peername(ssl) on socket ~p: ~p",
		   [Socket, {Port,PeerName}]),
	    {Port,PeerName};
	{error,_Reason} ->
	    {-1,"unknown"}
    end.

%% resolve

resolve(_) ->
    {ok,Name} = inet:gethostname(),
    Name.

%% close

close(ip_comm,Socket) ->
    Res =
	case (catch gen_tcp:close(Socket)) of
	    ok ->                  ok;
	    {error,Reason} ->      {error,Reason};
	    {'EXIT',{noproc,_}} -> {error,closed};
	    {'EXIT',Reason} ->     {error,Reason};
	    Otherwise ->           {error,Otherwise}
	end,
    ?vtrace("close(ip_comm) result: ~p",[Res]),
    Res;
close({ssl,_SSLConfig},Socket) ->
    Res =
	case (catch ssl:close(Socket)) of
	    ok ->                  ok;
	    {error,Reason} ->      {error,Reason};
	    {'EXIT',{noproc,_}} -> {error,closed};
	    {'EXIT',Reason} ->     {error,Reason};
	    Otherwise ->           {error,Otherwise}
	end,
    ?vtrace("close(ssl) result: ~p",[Res]),
    Res.

%% config (debug: {certfile, "/var/tmp/server_root/conf/ssl_server.pem"})

config(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,com_type,ip_comm) of
	ssl ->
	    case ssl_certificate_file(ConfigDB) of
		undefined ->
		    {error,
		     ?NICE("Directive SSLCertificateFile "
			   "not found in the config file")};
		SSLCertificateFile ->
		    {ssl,
		     SSLCertificateFile++
		     ssl_certificate_key_file(ConfigDB)++
		     ssl_verify_client(ConfigDB)++
		     ssl_ciphers(ConfigDB)++
		     ssl_password(ConfigDB)++
		     ssl_verify_depth(ConfigDB)++
		     ssl_ca_certificate_file(ConfigDB)}
	    end;
	ip_comm ->
	    ip_comm
    end.

ssl_certificate_file(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,ssl_certificate_file) of
	undefined ->
	    undefined;
	SSLCertificateFile ->
	    [{certfile,SSLCertificateFile}]
    end.

ssl_certificate_key_file(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,ssl_certificate_key_file) of
	undefined ->
	    [];
	SSLCertificateKeyFile ->
	    [{keyfile,SSLCertificateKeyFile}]
    end.

ssl_verify_client(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,ssl_verify_client) of
	undefined ->
	    [];
	SSLVerifyClient ->
	    [{verify,SSLVerifyClient}]
    end.

ssl_ciphers(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,ssl_ciphers) of
	undefined ->
	    [];
	Ciphers ->
	    [{ciphers, Ciphers}]
    end.

ssl_password(ConfigDB) ->
    case httpd_util:lookup(ConfigDB,ssl_password_callback_module) of
	undefined ->
	    [];
	Module ->
	    case httpd_util:lookup(ConfigDB, ssl_password_callback_function) of
		undefined ->
		    [];
		Function ->
		    case catch apply(Module, Function, []) of
			Password when list(Password) ->
			    [{password, Password}];
			Error ->
			    error_report(ssl_password,Module,Function,Error),
			    []
		    end
	    end
    end.

ssl_verify_depth(ConfigDB) ->
    case httpd_util:lookup(ConfigDB, ssl_verify_client_depth) of
	undefined ->
	    [];
	Depth ->
	    [{depth, Depth}]
    end.

ssl_ca_certificate_file(ConfigDB) ->
    case httpd_util:lookup(ConfigDB, ssl_ca_certificate_file) of
	undefined ->
	    [];
	File ->
	    [{cacertfile, File}]
    end.


error_report(Where,M,F,Error) ->
    error_logger:error_report([{?MODULE, Where}, {apply, {M, F, []}}, Error]).