[Unison-hackers] ipv6 support
Samuel Thibault
samuel.thibault at ens-lyon.org
Sat Jul 16 07:44:05 EDT 2005
Hi,
Here are patches for ipv6 support: just using getaddrinfo instead of
gethostbyname, and it works nicely. I turned ports into strings, so as
to be able to use port names too.
patch-unison is for version 2.9.1, patch-unison-svn is against current
subversion repository.
Regards,
Samuel
-------------- next part --------------
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
-------------- next part --------------
Index: remote.ml
===================================================================
--- remote.ml (r?vision 92)
+++ remote.ml (copie de travail)
@@ -811,25 +811,26 @@
let buildSocketConnection host port =
Util.convertUnixErrorsToFatal "canonizeRoot" (fun () ->
- let targetInetAddr =
- try
- inetAddr host
- 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;
- initConnection socket socket)
+ "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;
+ 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 rootName termInteract =
let remoteCmd =
@@ -844,7 +845,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
@@ -980,7 +981,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
@@ -1113,30 +1114,38 @@
(* 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 hostOpt portnum =
+let waitOnPort hostOpt 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 *)
- let addr =
- match hostOpt with
- Some host ->
- begin try inetAddr host with Not_found ->
- raise (Util.Fatal
- (Printf.sprintf
- "Can't find the IP address of the host (%s)" host))
- end
- | None ->
- Unix.inet_addr_any
- in
- Unix.bind listening
- (Unix.ADDR_INET (addr, portnum));
- (* Start listening, allow up to 1 pending request *)
- Unix.listen listening 1;
+ let host = match hostOpt with
+ Some host -> host
+ | None -> "" in
+ let rec loop = function
+ [] -> raise (Util.Fatal
+ (Printf.sprintf "Can't find host (%s:%s)" host 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 host (%s:%s): %s" ai.Unix.ai_canonname port
+ reason);
+ loop r)
+ end in
+ let listening = loop (Unix.getaddrinfo host port [ Unix.AI_SOCKTYPE
+ Unix.SOCK_STREAM ; Unix.AI_PASSIVE ]) in
Util.msg "server started\n";
while
(* Accept a connection *)
Index: clroot.ml
===================================================================
--- clroot.ml (r?vision 92)
+++ clroot.ml (copie de travail)
@@ -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
Index: clroot.mli
===================================================================
--- clroot.mli (r?vision 92)
+++ clroot.mli (copie de travail)
@@ -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
Index: remote.mli
===================================================================
--- remote.mli (r?vision 92)
+++ remote.mli (copie de travail)
@@ -36,7 +36,7 @@
(* Enter "server mode", reading and processing commands from a remote
client process until killed *)
val beAServer : unit -> unit
-val waitOnPort : string option -> int -> unit
+val waitOnPort : string option -> string -> unit
(* Whether the server should be killed when the client terminates *)
val killServer : bool Prefs.t
Index: uigtk.ml
===================================================================
--- uigtk.ml (r?vision 92)
+++ uigtk.ml (copie de travail)
@@ -655,21 +655,17 @@
`Local ->
Clroot.clroot2string(Clroot.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
Clroot.clroot2string(
Clroot.ConnectByShell((if !varLocalRemote=`SSH then "ssh" else "rsh"),
host,
(if user="" then None else Some user),
- portOpt,
+ Some portE#text,
Some file))
| `SOCKET ->
Clroot.clroot2string(
(* FIX: report an error if the port entry is not well formed *)
Clroot.ConnectBySocket(host,
- int_of_string(portE#text),
+ portE#text,
Some file)) in
let contCommand() =
try
Index: main.ml
===================================================================
--- main.ml (r?vision 92)
+++ main.ml (copie de travail)
@@ -183,15 +183,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
More information about the Unison-hackers
mailing list