You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2014/02/12 07:21:18 UTC

[29/33] ibrowse commit: updated refs/heads/import-master to 1167b0e

Add support for replication over IPv6 (part 1)

This change upgrades ibrowse to version 2.2.0. This version adds support
for IPv6 (https://github.com/cmullaparthi/ibrowse/pull/34).
This is part of COUCHDB-665.



git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1091709 13f79535-47bb-0310-9956-ffa450edef68


Project: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/commit/ca1ed965
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/tree/ca1ed965
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/diff/ca1ed965

Branch: refs/heads/import-master
Commit: ca1ed9659ed462917c36954d96734c589fef8193
Parents: 7232082
Author: Filipe David Borba Manana <fd...@apache.org>
Authored: Wed Apr 13 08:50:58 2011 +0000
Committer: Filipe David Borba Manana <fd...@apache.org>
Committed: Wed Apr 13 08:50:58 2011 +0000

----------------------------------------------------------------------
 Makefile.am             |  2 +-
 ibrowse.app.in          |  2 +-
 ibrowse.hrl             | 11 +++++++++-
 ibrowse_http_client.erl | 37 +++++++++++++++++++++++++++-----
 ibrowse_lib.erl         | 51 +++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 94 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ca1ed965/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index bfd52ba..869bd10 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,7 @@
 ## License for the specific language governing permissions and limitations under
 ## the License.
 
-ibrowseebindir = $(localerlanglibdir)/ibrowse-2.1.3/ebin
+ibrowseebindir = $(localerlanglibdir)/ibrowse-2.2.0/ebin
 
 ibrowse_file_collection = \
 	ibrowse.app.in \

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ca1ed965/ibrowse.app.in
----------------------------------------------------------------------
diff --git a/ibrowse.app.in b/ibrowse.app.in
index 875620d..af46d8a 100644
--- a/ibrowse.app.in
+++ b/ibrowse.app.in
@@ -1,6 +1,6 @@
 {application, ibrowse,
         [{description, "HTTP client application"},
-         {vsn, "2.1.3"},
+         {vsn, "2.2.0"},
          {modules, [ ibrowse, 
 		     ibrowse_http_client, 
 		     ibrowse_app, 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ca1ed965/ibrowse.hrl
----------------------------------------------------------------------
diff --git a/ibrowse.hrl b/ibrowse.hrl
index ebf3bb3..18dde82 100644
--- a/ibrowse.hrl
+++ b/ibrowse.hrl
@@ -1,7 +1,16 @@
 -ifndef(IBROWSE_HRL).
 -define(IBROWSE_HRL, "ibrowse.hrl").
 
--record(url, {abspath, host, port, username, password, path, protocol}).
+-record(url, {
+          abspath,
+          host,
+          port,
+          username,
+          password,
+          path,
+          protocol,
+          host_type  % 'hostname', 'ipv4_address' or 'ipv6_address'
+}).
 
 -record(lb_pid, {host_port, pid}).
 

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ca1ed965/ibrowse_http_client.erl
----------------------------------------------------------------------
diff --git a/ibrowse_http_client.erl b/ibrowse_http_client.erl
index 7d606e6..eb2bf31 100644
--- a/ibrowse_http_client.erl
+++ b/ibrowse_http_client.erl
@@ -35,6 +35,7 @@
         ]).
 
 -include("ibrowse.hrl").
+-include_lib("kernel/include/inet.hrl").
 
 -record(state, {host, port, connect_timeout,
                 inactivity_timer_ref,
@@ -489,13 +490,19 @@ do_connect(Host, Port, Options, #state{is_ssl      = true,
                                        use_proxy   = false,
                                        ssl_options = SSLOptions},
            Timeout) ->
-    ssl:connect(Host, Port, get_sock_options(Options, SSLOptions), Timeout);
+    ssl:connect(Host, Port, get_sock_options(Host, Options, SSLOptions), Timeout);
 do_connect(Host, Port, Options, _State, Timeout) ->
-    gen_tcp:connect(Host, Port, get_sock_options(Options, []), Timeout).
+    gen_tcp:connect(Host, Port, get_sock_options(Host, Options, []), Timeout).
 
-get_sock_options(Options, SSLOptions) ->
+get_sock_options(Host, Options, SSLOptions) ->
     Caller_socket_options = get_value(socket_options, Options, []),
-    Other_sock_options = filter_sock_options(SSLOptions ++ Caller_socket_options),
+    Ipv6Options = case is_ipv6_host(Host) of
+        true ->
+            [inet6];
+        false ->
+            []
+    end,
+    Other_sock_options = filter_sock_options(SSLOptions ++ Caller_socket_options ++ Ipv6Options),
     case lists:keysearch(nodelay, 1, Other_sock_options) of
         false ->
             [{nodelay, true}, binary, {active, false} | Other_sock_options];
@@ -503,6 +510,21 @@ get_sock_options(Options, SSLOptions) ->
             [binary, {active, false} | Other_sock_options]
     end.
 
+is_ipv6_host(Host) ->
+    case inet_parse:address(Host) of
+        {ok, {_, _, _, _, _, _, _, _}} ->
+            true;
+        {ok, {_, _, _, _}} ->
+            false;
+        _  ->
+            case inet:gethostbyname(Host) of
+                {ok, #hostent{h_addrtype = inet6}} ->
+                    true;
+                _ ->
+                    false
+            end
+    end.
+
 %% We don't want the caller to specify certain options
 filter_sock_options(Opts) ->
     lists:filter(fun({active, _}) ->
@@ -1278,7 +1300,12 @@ handle_response(#request{from=From, stream_to=StreamTo, req_id=ReqId,
                        reply_buffer  = RepBuf,
                        recvd_headers = RespHeaders}=State) when SaveResponseToFile /= false ->
     Body = RepBuf,
-    ok = file:close(Fd),
+    case Fd of
+        undefined -> 
+            ok;
+        _ -> 
+            ok = file:close(Fd)
+    end,
     ResponseBody = case TmpFilename of
                        undefined ->
                            Body;

http://git-wip-us.apache.org/repos/asf/couchdb-ibrowse/blob/ca1ed965/ibrowse_lib.erl
----------------------------------------------------------------------
diff --git a/ibrowse_lib.erl b/ibrowse_lib.erl
index 696d0f6..3cbe3ac 100644
--- a/ibrowse_lib.erl
+++ b/ibrowse_lib.erl
@@ -180,7 +180,19 @@ get_value(Tag, TVL) ->
     V.
 
 parse_url(Url) ->
-    parse_url(Url, get_protocol, #url{abspath=Url}, []).
+    case parse_url(Url, get_protocol, #url{abspath=Url}, []) of
+        #url{host_type = undefined, host = Host} = UrlRec ->
+            case inet_parse:address(Host) of
+                {ok, {_, _, _, _, _, _, _, _}} ->
+                    UrlRec#url{host_type = ipv6_address};
+                {ok, {_, _, _, _}} ->
+                    UrlRec#url{host_type = ipv4_address};
+                _ ->
+                    UrlRec#url{host_type = hostname}
+            end;
+        Else ->
+            Else
+    end.
 
 parse_url([$:, $/, $/ | _], get_protocol, Url, []) ->
     {invalid_uri_1, Url};
@@ -215,6 +227,21 @@ parse_url([$@ | T], get_username, Url, TmpAcc) ->
               Url#url{username = lists:reverse(TmpAcc),
                       password = ""},
               []);
+parse_url([$[ | T], get_username, Url, []) ->
+    % IPv6 address literals are enclosed by square brackets:
+    %     http://www.ietf.org/rfc/rfc2732.txt
+    parse_url(T, get_ipv6_address, Url#url{host_type = ipv6_address}, []);
+parse_url([$[ | T], get_username, _Url, TmpAcc) ->
+    {error, {invalid_username_or_host, lists:reverse(TmpAcc) ++ "[" ++ T}};
+parse_url([$[ | _], get_password, _Url, []) ->
+    {error, missing_password};
+parse_url([$[ | T], get_password, Url, TmpAcc) ->
+    % IPv6 address literals are enclosed by square brackets:
+    %     http://www.ietf.org/rfc/rfc2732.txt
+    parse_url(T, get_ipv6_address,
+              Url#url{host_type = ipv6_address,
+                      password = lists:reverse(TmpAcc)},
+              []);
 parse_url([$@ | T], get_password, Url, TmpAcc) ->
     parse_url(T, get_host, 
               Url#url{password = lists:reverse(TmpAcc)},
@@ -236,6 +263,28 @@ parse_url([H | T], get_password, Url, TmpAcc) when H == $/;
             username = undefined,
             password = undefined,
            path = Path};
+parse_url([$] | T], get_ipv6_address, #url{protocol = Prot} = Url, TmpAcc) ->
+    Addr = lists:reverse(TmpAcc),
+    case inet_parse:address(Addr) of
+        {ok, {_, _, _, _, _, _, _, _}} ->
+            Url2 = Url#url{host = Addr, port = default_port(Prot)},
+            case T of
+                [$: | T2] ->
+                    parse_url(T2, get_port, Url2, []);
+                [$/ | T2] ->
+                    Url2#url{path = [$/ | T2]};
+                [$? | T2] ->
+                    Url2#url{path = [$/, $? | T2]};
+                [] ->
+                    Url2#url{path = "/"};
+                _ ->
+                    {error, {invalid_host, "[" ++ Addr ++ "]" ++ T}}
+            end;
+        _ ->
+            {error, {invalid_ipv6_address, Addr}}
+    end;
+parse_url([$[ | T], get_host, #url{} = Url, []) ->
+    parse_url(T, get_ipv6_address, Url#url{host_type = ipv6_address}, []);
 parse_url([$: | T], get_host, #url{} = Url, TmpAcc) ->
     parse_url(T, get_port, 
               Url#url{host = lists:reverse(TmpAcc)},