[MLton] INetSock problems, hton/ntoh usage
Matthew Fluet
fluet at tti-c.org
Mon Mar 26 08:38:17 PST 2007
Matthew Fluet wrote:
> Vesa Karvonen wrote:
>> The port number of a socket is a 16-bit integer (the sin_port field of
>> struct sockaddr_in). OTOH, the current net code in MLton represents port
>> numbers as C_Int.t values which usually aren't 16-bit integers.
>
> I think the better solution would be to use Word16.word for ports in the
> INetSock structure (and C-side functions in INetSock.c). It probably
> isn't worth creating a whole C_InPort structure, when we know it should
> be equivalent to Word16. My general approach has been to follow the C
> types as closely as possible, since it makes the C-side code very simple.
>
> The Basis Library doesn't specify the behavior of INetSock.toAddr (ia,
> i) when the port i (of ML type int) is too large to be represented by
> the C-side representation of a port. I think we currently would raise
> the Overflow exception, which seems reasonable.
I propose the following patch. (This raises SysError with inval rather
than Overflow when the port cannot be converted from Int.int to
Word16.word without truncation.) This works with regression/socket.sml
and regression/echo.sml, as well as the testcase posed by
http://mlton.org/pipermail/mlton/2006-December/029465.html
Vesa, does this work with your smlbot?
-------------- next part --------------
Index: runtime/basis-ffi.h
===================================================================
--- runtime/basis-ffi.h (revision 5441)
+++ runtime/basis-ffi.h (working copy)
@@ -927,8 +927,8 @@
extern const C_Int_t Socket_INetSock_Ctl_TCP_NODELAY;
void Socket_INetSock_fromAddr(Vector(Word8_t));
void Socket_INetSock_getInAddr(Array(Word8_t));
-C_Int_t Socket_INetSock_getPort(void);
-void Socket_INetSock_toAddr(Vector(Word8_t),C_Int_t,Array(Word8_t),Ref(C_Socklen_t));
+Word16_t Socket_INetSock_getPort(void);
+void Socket_INetSock_toAddr(Vector(Word8_t),Word16_t,Array(Word8_t),Ref(C_Socklen_t));
C_Errno_t(C_Int_t) Socket_listen(C_Sock_t,C_Int_t);
extern const C_Int_t Socket_MSG_CTRUNC;
extern const C_Int_t Socket_MSG_DONTROUTE;
Index: runtime/basis/Net/Socket/INetSock.c
===================================================================
--- runtime/basis/Net/Socket/INetSock.c (revision 5441)
+++ runtime/basis/Net/Socket/INetSock.c (working copy)
@@ -1,17 +1,17 @@
#include "platform.h"
void
-Socket_INetSock_toAddr (Vector(Word8_t) in_addr, C_Int_t port,
+Socket_INetSock_toAddr (Vector(Word8_t) in_addr, Word16_t port,
Array(Word8_t) addr, Ref(C_Socklen_t) addrlen) {
struct sockaddr_in *sa = (struct sockaddr_in*)addr;
sa->sin_family = AF_INET;
- sa->sin_port = port;
+ sa->sin_port = (uint16_t)port;
sa->sin_addr = *(const struct in_addr*)in_addr;
*((socklen_t*)addrlen) = sizeof(struct sockaddr_in);
}
-static int fromAddr_port;
+static uint16_t fromAddr_port;
static struct in_addr fromAddr_in_addr;
void Socket_INetSock_fromAddr (Vector(Word8_t) addr) {
@@ -22,8 +22,8 @@
fromAddr_in_addr = sa->sin_addr;
}
-C_Int_t Socket_INetSock_getPort (void) {
- return fromAddr_port;
+Word16_t Socket_INetSock_getPort (void) {
+ return (Word16_t)fromAddr_port;
}
void Socket_INetSock_getInAddr (Array(Word8_t) addr) {
Index: runtime/gen/basis-ffi.def
===================================================================
--- runtime/gen/basis-ffi.def (revision 5441)
+++ runtime/gen/basis-ffi.def (working copy)
@@ -810,8 +810,8 @@
Socket.INetSock.Ctl.TCP_NODELAY = _const : C_Int.t
Socket.INetSock.fromAddr = _import : Word8.t vector -> unit
Socket.INetSock.getInAddr = _import : Word8.t array -> unit
-Socket.INetSock.getPort = _import : unit -> C_Int.t
-Socket.INetSock.toAddr = _import : Word8.t vector * C_Int.t * Word8.t array * C_Socklen.t ref -> unit
+Socket.INetSock.getPort = _import : unit -> Word16.t
+Socket.INetSock.toAddr = _import : Word8.t vector * Word16.t * Word8.t array * C_Socklen.t ref -> unit
Socket.MSG_CTRUNC = _const : C_Int.t
Socket.MSG_DONTROUTE = _const : C_Int.t
Socket.MSG_DONTWAIT = _const : C_Int.t
Index: runtime/gen/basis-ffi.h
===================================================================
--- runtime/gen/basis-ffi.h (revision 5441)
+++ runtime/gen/basis-ffi.h (working copy)
@@ -927,8 +927,8 @@
extern const C_Int_t Socket_INetSock_Ctl_TCP_NODELAY;
void Socket_INetSock_fromAddr(Vector(Word8_t));
void Socket_INetSock_getInAddr(Array(Word8_t));
-C_Int_t Socket_INetSock_getPort(void);
-void Socket_INetSock_toAddr(Vector(Word8_t),C_Int_t,Array(Word8_t),Ref(C_Socklen_t));
+Word16_t Socket_INetSock_getPort(void);
+void Socket_INetSock_toAddr(Vector(Word8_t),Word16_t,Array(Word8_t),Ref(C_Socklen_t));
C_Errno_t(C_Int_t) Socket_listen(C_Sock_t,C_Int_t);
extern const C_Int_t Socket_MSG_CTRUNC;
extern const C_Int_t Socket_MSG_DONTROUTE;
Index: runtime/gen/basis-ffi.sml
===================================================================
--- runtime/gen/basis-ffi.sml (revision 5441)
+++ runtime/gen/basis-ffi.sml (working copy)
@@ -1132,8 +1132,8 @@
end
val fromAddr = _import "Socket_INetSock_fromAddr" : (Word8.t) vector -> unit;
val getInAddr = _import "Socket_INetSock_getInAddr" : (Word8.t) array -> unit;
-val getPort = _import "Socket_INetSock_getPort" : unit -> C_Int.t;
-val toAddr = _import "Socket_INetSock_toAddr" : (Word8.t) vector * C_Int.t * (Word8.t) array * (C_Socklen.t) ref -> unit;
+val getPort = _import "Socket_INetSock_getPort" : unit -> Word16.t;
+val toAddr = _import "Socket_INetSock_toAddr" : (Word8.t) vector * Word16.t * (Word8.t) array * (C_Socklen.t) ref -> unit;
end
val listen = _import "Socket_listen" : C_Sock.t * C_Int.t -> (C_Int.t) C_Errno.t;
val MSG_CTRUNC = _const "Socket_MSG_CTRUNC" : C_Int.t;
Index: basis-library/net/inet-sock.sml
===================================================================
--- basis-library/net/inet-sock.sml (revision 5441)
+++ basis-library/net/inet-sock.sml (working copy)
@@ -19,18 +19,15 @@
fun toAddr (in_addr, port) =
let
- val port = C_Int.fromInt port
- val port = Net.C_Int.hton port
+ val port = Word16.fromInt port
+ handle Overflow => PosixError.raiseSys PosixError.inval
+ val port = Net.Word16.hton port
+ val (sa, salen, finish) = Socket.new_sock_addr ()
+ val _ = Prim.toAddr (NetHostDB.inAddrToWord8Vector in_addr,
+ port, sa, salen)
+
in
- if C_Int.< (port, 0) orelse C_Int.>= (port, 0x10000)
- then PosixError.raiseSys PosixError.inval
- else let
- val (sa, salen, finish) = Socket.new_sock_addr ()
- val _ = Prim.toAddr (NetHostDB.inAddrToWord8Vector in_addr,
- port, sa, salen)
- in
- finish ()
- end
+ finish ()
end
fun any port = toAddr (NetHostDB.any (), port)
@@ -39,8 +36,8 @@
let
val () = Prim.fromAddr (Socket.unpackSockAddr sa)
val port = Prim.getPort ()
- val port = Net.C_Int.ntoh port
- val port = C_Int.toInt port
+ val port = Net.Word16.ntoh port
+ val port = Word16.toInt port
val (ia, finish) = NetHostDB.new_in_addr ()
val _ = Prim.getInAddr (NetHostDB.preInAddrToWord8Array ia)
in
Index: basis-library/net/net.sig
===================================================================
--- basis-library/net/net.sig (revision 5441)
+++ basis-library/net/net.sig (working copy)
@@ -7,6 +7,11 @@
signature NET =
sig
+ structure Word16 :
+ sig
+ val hton: Word16.word -> Word16.word
+ val ntoh: Word16.word -> Word16.word
+ end
structure C_Int :
sig
val hton: C_Int.t -> C_Int.t
Index: basis-library/primitive/basis-ffi.sml
===================================================================
--- basis-library/primitive/basis-ffi.sml (revision 5441)
+++ basis-library/primitive/basis-ffi.sml (working copy)
@@ -1132,8 +1132,8 @@
end
val fromAddr = _import "Socket_INetSock_fromAddr" : (Word8.t) vector -> unit;
val getInAddr = _import "Socket_INetSock_getInAddr" : (Word8.t) array -> unit;
-val getPort = _import "Socket_INetSock_getPort" : unit -> C_Int.t;
-val toAddr = _import "Socket_INetSock_toAddr" : (Word8.t) vector * C_Int.t * (Word8.t) array * (C_Socklen.t) ref -> unit;
+val getPort = _import "Socket_INetSock_getPort" : unit -> Word16.t;
+val toAddr = _import "Socket_INetSock_toAddr" : (Word8.t) vector * Word16.t * (Word8.t) array * (C_Socklen.t) ref -> unit;
end
val listen = _import "Socket_listen" : C_Sock.t * C_Int.t -> (C_Int.t) C_Errno.t;
val MSG_CTRUNC = _const "Socket_MSG_CTRUNC" : C_Int.t;
More information about the MLton
mailing list