aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2014-09-29 08:59:41 +0200
committerErlang/OTP <[email protected]>2014-09-29 08:59:41 +0200
commit853af0f4739e53e32c655373488c0fadcab9e421 (patch)
tree5a06dd784ba6213da467edc6ed631c6d82725673
parent743ed31108ee555db18d9833186865e85e34333e (diff)
parent1e5844012ab8c3963e2d3b0f05adc2a7b2b0afb7 (diff)
downloadotp-853af0f4739e53e32c655373488c0fadcab9e421.tar.gz
otp-853af0f4739e53e32c655373488c0fadcab9e421.tar.bz2
otp-853af0f4739e53e32c655373488c0fadcab9e421.zip
Merge branch 'hans/eldap/tcpoptions/OTP-12171' into maint-17
* hans/eldap/tcpoptions/OTP-12171: eldap: update version eldap: New very basic test suite. eldap: Enable all tcp options in eldap:open
-rw-r--r--lib/eldap/doc/src/eldap.xml4
-rw-r--r--lib/eldap/src/eldap.erl65
-rw-r--r--lib/eldap/test/Makefile1
-rw-r--r--lib/eldap/test/eldap_connections_SUITE.erl126
-rw-r--r--lib/eldap/vsn.mk3
5 files changed, 189 insertions, 10 deletions
diff --git a/lib/eldap/doc/src/eldap.xml b/lib/eldap/doc/src/eldap.xml
index 8009a8d6a3..dbd478fb17 100644
--- a/lib/eldap/doc/src/eldap.xml
+++ b/lib/eldap/doc/src/eldap.xml
@@ -75,7 +75,9 @@ filter() See present/1, substrings/2,
<p>Setup a connection to an LDAP server, the <c>HOST</c>'s are tried in order.</p>
<p>The log function takes three arguments, <c>fun(Level, FormatString, [FormatArg]) end</c>.</p>
<p>Timeout set the maximum time in milliseconds that each server request may take.</p>
- <p>Currently, the only TCP socket option accepted is <c>inet6</c>. Default is <c>inet</c>.</p>
+ <p>All TCP socket options are accepted except
+ <c>active</c>, <c>binary</c>, <c>deliver</c>, <c>list</c>, <c>mode</c> and <c>packet</c>
+ </p>
</desc>
</func>
<func>
diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl
index 1cd328cde3..416334e365 100644
--- a/lib/eldap/src/eldap.erl
+++ b/lib/eldap/src/eldap.erl
@@ -12,6 +12,7 @@
-vc('$Id$ ').
-export([open/1,open/2,simple_bind/3,controlling_process/2,
start_tls/2, start_tls/3,
+ getopts/2,
baseObject/0,singleLevel/0,wholeSubtree/0,close/1,
equalityMatch/2,greaterOrEqual/2,lessOrEqual/2,
approxMatch/2,search/2,substrings/2,present/1,
@@ -92,6 +93,15 @@ start_tls(Handle, TlsOptions, Timeout) ->
recv(Handle).
%%% --------------------------------------------------------------------
+%%% Ask for option values on the socket.
+%%% Warning: This is an undocumented function for testing purposes only.
+%%% Use at own risk...
+%%% --------------------------------------------------------------------
+getopts(Handle, OptNames) when is_pid(Handle), is_list(OptNames) ->
+ send(Handle, {getopts, OptNames}),
+ recv(Handle).
+
+%%% --------------------------------------------------------------------
%%% Shutdown connection (and process) asynchronous.
%%% --------------------------------------------------------------------
@@ -374,24 +384,35 @@ parse_args([{sslopts, Opts}|T], Cpid, Data) when is_list(Opts) ->
parse_args([{sslopts, _}|T], Cpid, Data) ->
parse_args(T, Cpid, Data);
parse_args([{tcpopts, Opts}|T], Cpid, Data) when is_list(Opts) ->
- parse_args(T, Cpid, Data#eldap{tcp_opts = inet6_opt(Opts) ++ Data#eldap.tcp_opts});
+ parse_args(T, Cpid, Data#eldap{tcp_opts = tcp_opts(Opts,Cpid,Data#eldap.tcp_opts)});
parse_args([{log, F}|T], Cpid, Data) when is_function(F) ->
parse_args(T, Cpid, Data#eldap{log = F});
parse_args([{log, _}|T], Cpid, Data) ->
parse_args(T, Cpid, Data);
parse_args([H|_], Cpid, _) ->
send(Cpid, {error,{wrong_option,H}}),
+ unlink(Cpid),
exit(wrong_option);
parse_args([], _, Data) ->
Data.
-inet6_opt(Opts) ->
- case proplists:get_value(inet6, Opts) of
+tcp_opts([Opt|Opts], Cpid, Acc) ->
+ Key = if is_atom(Opt) -> Opt;
+ is_tuple(Opt) -> element(1,Opt)
+ end,
+ case lists:member(Key,[active,binary,deliver,list,mode,packet]) of
+ false ->
+ tcp_opts(Opts, Cpid, [Opt|Acc]);
true ->
- [inet6];
- _ ->
- []
- end.
+ tcp_opts_error(Opt, Cpid)
+ end;
+tcp_opts([], _Cpid, Acc) -> Acc.
+
+tcp_opts_error(Opt, Cpid) ->
+ send(Cpid, {error, {{forbidden_tcp_option,Opt},
+ "This option affects the eldap functionality and can't be set by user"}}),
+ unlink(Cpid),
+ exit(forbidden_tcp_option).
%%% Try to connect to the hosts in the listed order,
%%% and stop with the first one to which a successful
@@ -466,6 +487,36 @@ loop(Cpid, Data) ->
unlink(Cpid),
exit(closed);
+ {From, {getopts, OptNames}} ->
+ Result =
+ try
+ [case OptName of
+ port -> {port, Data#eldap.port};
+ log -> {log, Data#eldap.log};
+ timeout -> {timeout, Data#eldap.timeout};
+ ssl -> {ssl, Data#eldap.ldaps};
+ {sslopts, SslOptNames} when Data#eldap.using_tls==true ->
+ case ssl:getopts(Data#eldap.fd, SslOptNames) of
+ {ok,SslOptVals} -> {sslopts, SslOptVals};
+ {error,Reason} -> throw({error,Reason})
+ end;
+ {sslopts, _} ->
+ throw({error,no_tls});
+ {tcpopts, TcpOptNames} ->
+ case inet:getopts(Data#eldap.fd, TcpOptNames) of
+ {ok,TcpOptVals} -> {tcpopts, TcpOptVals};
+ {error,Posix} -> throw({error,Posix})
+ end
+ end || OptName <- OptNames]
+ of
+ OptsList -> {ok,OptsList}
+ catch
+ throw:Error -> Error;
+ Class:Error -> {error,{Class,Error}}
+ end,
+ send(From, Result),
+ ?MODULE:loop(Cpid, Data);
+
{Cpid, 'EXIT', Reason} ->
?PRINT("Got EXIT from Cpid, reason=~p~n",[Reason]),
exit(Reason);
diff --git a/lib/eldap/test/Makefile b/lib/eldap/test/Makefile
index 3c5810eece..24e71cebaa 100644
--- a/lib/eldap/test/Makefile
+++ b/lib/eldap/test/Makefile
@@ -28,6 +28,7 @@ INCLUDES= -I. -I ../include
# ----------------------------------------------------
MODULES= \
+ eldap_connections_SUITE \
eldap_basic_SUITE
ERL_FILES= $(MODULES:%=%.erl)
diff --git a/lib/eldap/test/eldap_connections_SUITE.erl b/lib/eldap/test/eldap_connections_SUITE.erl
new file mode 100644
index 0000000000..4c8aa9c2cf
--- /dev/null
+++ b/lib/eldap/test/eldap_connections_SUITE.erl
@@ -0,0 +1,126 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2014. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(eldap_connections_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+%-include_lib("eldap/include/eldap.hrl").
+
+
+all() ->
+ [
+ tcp_connection,
+ tcp_inet6_connection,
+ tcp_connection_option,
+ tcp_inet6_connection_option
+ ].
+
+
+init_per_suite(Config) -> Config.
+
+end_per_suite(_Config) -> ok.
+
+
+init_per_testcase(_TestCase, Config) ->
+ {ok,Sl} = gen_tcp:listen(0,[]),
+ {ok,Sl6} = gen_tcp:listen(0,[inet6]),
+ [{listen_socket,Sl}, {listen_socket6,Sl6} | Config].
+
+end_per_testcase(_TestCase, Config) ->
+ catch gen_tcp:close( proplists:get_value(listen_socket, Config) ),
+ catch gen_tcp:close( proplists:get_value(listen_socket6, Config) ),
+ ok.
+
+%%%================================================================
+%%%
+%%% Test cases
+%%%
+%%%----------------------------------------------------------------
+tcp_connection(Config) ->
+ do_tcp_connection(Config, listen_socket, "localhost", []).
+
+tcp_inet6_connection(Config) ->
+ do_tcp_connection(Config, listen_socket6, "::", [{tcpopts,[inet6]}]).
+
+
+do_tcp_connection(Config, SockKey, Host, Opts) ->
+ Sl = proplists:get_value(SockKey, Config),
+ {ok,{_,Port}} = inet:sockname(Sl),
+ case eldap:open([Host], [{port,Port}|Opts]) of
+ {ok,_H} ->
+ case gen_tcp:accept(Sl,1000) of
+ {ok,_S} -> ok;
+ {error,timeout} -> ct:fail("server side accept timeout",[])
+ end;
+ Other -> ct:fail("eldap:open failed: ~p",[Other])
+ end.
+
+%%%----------------------------------------------------------------
+tcp_connection_option(Config) ->
+ do_tcp_connection_option(Config, listen_socket, "localhost", []).
+
+tcp_inet6_connection_option(Config) ->
+ do_tcp_connection_option(Config, listen_socket6, "::", [{tcpopts,[inet6]}]).
+
+
+do_tcp_connection_option(Config, SockKey, Host, Opts) ->
+ Sl = proplists:get_value(SockKey, Config),
+ {ok,{_,Port}} = inet:sockname(Sl),
+
+ %% Make an option value to test. The option must be implemented on all
+ %% platforms that we test on. Must check what the default value is
+ %% so we don't happen to choose that particular value.
+ {ok,[{linger,DefaultLinger}]} = inet:getopts(Sl, [linger]),
+ TestLinger = case DefaultLinger of
+ {false,_} -> {true,5};
+ {true,_} -> {false,0}
+ end,
+
+ case catch eldap:open([Host],
+ [{port,Port},{tcpopts,[{linger,TestLinger}]}|Opts]) of
+ {ok,H} ->
+ case gen_tcp:accept(Sl,1000) of
+ {ok,_} ->
+ case eldap:getopts(H, [{tcpopts,[linger]}]) of
+ {ok,[{tcpopts,[{linger,ActualLinger}]}]} ->
+ case ActualLinger of
+ TestLinger ->
+ ok;
+ DefaultLinger ->
+ ct:fail("eldap:getopts: 'linger' didn't change,"
+ " got ~p (=default) expected ~p",
+ [ActualLinger,TestLinger]);
+ _ ->
+ ct:fail("eldap:getopts: bad 'linger', got ~p expected ~p",
+ [ActualLinger,TestLinger])
+ end;
+ Other ->
+ ct:fail("eldap:getopts: bad result ~p",[Other])
+ end;
+ {error,timeout} ->
+ ct:fail("server side accept timeout",[])
+ end;
+
+ Other ->
+ ct:fail("eldap:open failed: ~p",[Other])
+ end.
+
+%%%----------------------------------------------------------------
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index efdc30b476..5e32f92fa8 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1,2 +1 @@
-ELDAP_VSN = 1.0.3
-
+ELDAP_VSN = 1.0.4 \ No newline at end of file