Package: unison
Version: 2.9.1-2
Severity: wishlist
Tags: patch, upstream

Hi,

Here is a patch to handle IPv6: replaced gethostbyname by getaddrinfo,
which prefers port strings, and people may indeed want to use strings,
so the patch makes unison use strings for ports as well.

Regards,
Samuel Thibault

-- System Information:
Debian Release: 3.1
  APT prefers unstable
  APT policy: (100, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)
Kernel: Linux 2.6.11
Locale: [EMAIL PROTECTED], [EMAIL PROTECTED] (charmap=ISO-8859-15)

Versions of packages unison depends on:
ii  libc6                       2.3.2.ds1-20 GNU C Library: Shared libraries an

-- no debconf information
diff -ur unison-2.9.1/main.ml unison-2.9.1-mine/main.ml
--- unison-2.9.1/main.ml        2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/main.ml   2005-03-30 02:15:01.000000000 +0200
@@ -174,15 +174,7 @@
 
 (* Start a socket server if requested *)
 begin try
-  let i =
-    match Util.StringMap.find socketPrefName argv with
-      [] ->
-        assert false
-    | i::_ ->
-        try int_of_string i with Failure _ ->
-          Util.msg "-socket must be followed by a number\n";
-          exit 1
-  in
+  let i = List.hd (Util.StringMap.find socketPrefName argv) in
   catch_all (fun () ->
     Os.createUnisonDir();
     Remote.waitOnPort i);
diff -ur unison-2.9.1/remote.ml unison-2.9.1-mine/remote.ml
--- unison-2.9.1/remote.ml      2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/remote.ml 2005-03-30 02:24:04.000000000 +0200
@@ -1037,25 +1037,24 @@
   Lwt.return conn))
 
 let buildSocketConnection host port =
-  let targetInetAddr =
-    try
-      let targetHostEntry = Unix.gethostbyname host in
-      targetHostEntry.Unix.h_addr_list.(0)
-    with Not_found ->
+  let rec loop = function
+    [] -> 
       raise (Util.Fatal
-               (Printf.sprintf
-                  "Can't find the IP address of the server (%s)" host))
-  in
-  (* create a socket to talk to the remote host *)
-  let socket = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
-  begin try
-    Unix.connect socket (Unix.ADDR_INET(targetInetAddr,port))
-  with
-    Unix.Unix_error (_, _, reason) ->
-      raise (Util.Fatal
-               (Printf.sprintf "Can't connect to server (%s): %s" host reason))
-  end;
-  Lwt_unix.run (initConnection socket socket)
+              (Printf.sprintf
+                 "Can't find the IP address of the server (%s:%s)" host port))
+  | ai::r ->
+    (* create a socket to talk to the remote host *)
+    let socket = Unix.socket ai.Unix.ai_family ai.Unix.ai_socktype 
ai.Unix.ai_protocol in
+    begin try
+      Unix.connect socket ai.Unix.ai_addr;
+      Lwt_unix.run (initConnection socket socket)
+    with
+      Unix.Unix_error (_, _, reason) ->
+       (Util.warn
+         (Printf.sprintf "Can't connect to server (%s:%s): %s" host port 
reason);
+        loop r)
+    end
+  in loop (Unix.getaddrinfo host port [ Unix.AI_SOCKTYPE Unix.SOCK_STREAM ])
 
 let buildShellConnection shell host userOpt portOpt =
   let (in_ch, out_ch) =
@@ -1071,7 +1070,7 @@
     let portArgs =
       match portOpt with
         None -> []
-      | Some port -> ["-p"; string_of_int port] in
+      | Some port -> ["-p"; port] in
     let shellCmd =
       (if shell = "ssh" then
         Prefs.read sshCmd
@@ -1197,18 +1196,31 @@
 (* Used by the socket mechanism: Create a socket on portNum and wait
    for a request. Each request is processed by commandLoop. When a
    session finishes, the server waits for another request. *)
-let waitOnPort portnum =
+let waitOnPort port =
   Util.convertUnixErrorsToFatal
     "waiting on port"
     (fun () ->
-      (* Open a socket to listen for queries *)
-      let listening = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
-      (* Allow reuse of local addresses for bind *)
-      Unix.setsockopt listening Unix.SO_REUSEADDR true;
-      (* Bind the socket to portnum on the local host *)
-      Unix.bind listening (Unix.ADDR_INET(Unix.inet_addr_any,portnum));
-      (* Start listening, allow up to 1 pending request *)
-      Unix.listen listening 1;
+      let rec loop = function
+        [] -> raise (Util.Fatal
+               (Printf.sprintf "Can't find local port %s" port))
+      | ai::r ->
+       (* Open a socket to listen for queries *)
+        let socket = Unix.socket ai.Unix.ai_family ai.Unix.ai_socktype 
ai.Unix.ai_protocol in
+       begin try
+         (* Allow reuse of local addresses for bind *)
+         Unix.setsockopt socket Unix.SO_REUSEADDR true;
+         (* Bind the socket to portnum on the local host *)
+         Unix.bind socket ai.Unix.ai_addr;
+         (* Start listening, allow up to 1 pending request *)
+         Unix.listen socket 1;
+         socket
+       with
+         Unix.Unix_error (_, _, reason) ->
+           (Util.warn
+             (Printf.sprintf "Can't bind to local port (%s:%s): %s" 
ai.Unix.ai_canonname port reason);
+            loop r)
+       end in
+      let listening = loop (Unix.getaddrinfo "" port [ Unix.AI_SOCKTYPE 
Unix.SOCK_STREAM ; Unix.AI_PASSIVE ]) in
       Util.msg "server started\n";
       while
         (* Accept a connection *)
diff -ur unison-2.9.1/remote.mli unison-2.9.1-mine/remote.mli
--- unison-2.9.1/remote.mli     2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/remote.mli        2005-03-30 02:13:53.000000000 +0200
@@ -64,7 +64,7 @@
 (* Enter "server mode", reading and processing commands from a remote
    client process until killed *)
 val beAServer : unit -> unit
-val waitOnPort : int -> unit
+val waitOnPort : string -> unit
 
 (* Whether the server should be killed when the client terminates *)
 val killServer : bool Prefs.t
diff -ur unison-2.9.1/uigtk.ml unison-2.9.1-mine/uigtk.ml
--- unison-2.9.1/uigtk.ml       2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/uigtk.ml  2005-03-30 01:58:19.000000000 +0200
@@ -655,21 +655,17 @@
       `Local ->
         Uri.clroot2string(Uri.ConnectLocal(Some file))
     | `SSH | `RSH ->
-        let portOpt =
-          (* FIX: report an error if the port entry is not well formed *)
-          try Some(int_of_string(portE#text))
-          with _ -> None in
         Uri.clroot2string(
         Uri.ConnectByShell((if !varLocalRemote=`SSH then "ssh" else "rsh"),
                            host,
                            (if user="" then None else Some user),
-                           portOpt,
+                           Some portE#text,
                            Some file))
     | `SOCKET ->
         Uri.clroot2string(
         (* FIX: report an error if the port entry is not well formed *)
         Uri.ConnectBySocket(host,
-                            int_of_string(portE#text),
+                            portE#text,
                             Some file)) in
   let contCommand() =
     try
diff -ur unison-2.9.1/uri.ml unison-2.9.1-mine/uri.ml
--- unison-2.9.1/uri.ml 2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/uri.ml    2005-03-30 01:34:08.000000000 +0200
@@ -33,11 +33,11 @@
           string        (* shell = "rsh" or "ssh" *)
         * string        (* name of host *)
         * string option (* user name to log in as *)
-        * int option    (* port *)
+        * string option (* port *)
         * string option (* root of replica in host fs *)
   | ConnectBySocket of
           string        (* name of host *)
-        * int           (* port where server should be listening *)
+        * string        (* port where server should be listening *)
         * string option (* root of replica in host fs *)
 
 (* Internal datatypes used in parsing command-line roots *)
@@ -107,13 +107,13 @@
     (Some host,s')
   else (None,s)
 
-let colonPortRegexp = Str.regexp ":[0-9]+"
+let colonPortRegexp = Str.regexp ":[^/]+"
 let getPort s =
   if Str.string_match colonPortRegexp s 0
   then
     let colonPort = Str.matched_string s in
     let len = String.length colonPort in
-    let port = int_of_string(String.sub colonPort 1 (len-1)) in
+    let port = String.sub colonPort 1 (len-1) in
     let s' = Str.string_after s len in
     (Some port,s')
   else (None,s)
@@ -178,11 +178,11 @@
     else Printf.sprintf "file:///%s" s
     else s
 | ConnectBySocket(h,p,s) ->
-    Printf.sprintf "socket://%s:%d/%s" h p
+    Printf.sprintf "socket://%s:%s/%s" h p
       (match s with None -> "" | Some x -> x)
 | ConnectByShell(sh,h,u,p,s) ->
     let user = match u with None -> "" | Some x -> x^"@" in
-    let port = match p with None -> "" | Some x -> ":"^(string_of_int x) in
+    let port = match p with None -> "" | Some x -> ":"^x in
     let path = match s with None -> "" | Some x -> x in
     Printf.sprintf "%s://%s%s%s/%s" sh user h port path
 
diff -ur unison-2.9.1/uri.mli unison-2.9.1-mine/uri.mli
--- unison-2.9.1/uri.mli        2002-04-11 07:13:23.000000000 +0200
+++ unison-2.9.1-mine/uri.mli   2005-03-30 01:35:47.000000000 +0200
@@ -10,11 +10,11 @@
           string        (* shell = "rsh" or "ssh" *)
         * string        (* name of host *)
         * string option (* user name to log in as *)
-        * int option    (* port *)
+        * string option (* port *)
         * string option (* root of replica in host fs *)
   | ConnectBySocket of
           string        (* name of host *)
-        * int           (* port where server should be listening *)
+        * string        (* port where server should be listening *)
         * string option (* root of replica in host fs *)
 
 val clroot2string : clroot -> string

Reply via email to