1 (* Copyright (C
) 2002-2006, 2008 Henry Cejtin
, Matthew Fluet
, Suresh
2 * Jagannathan
, and Stephen Weeks
.
4 * MLton is released under a BSD
-style license
.
5 * See the file MLton
-LICENSE for details
.
8 structure NetHostDB
: NET_HOST_DB_EXTRA
=
10 structure Prim
= PrimitiveFFI
.NetHostDB
12 (* network byte
order (big
-endian
) *)
13 type pre_in_addr
= Word8.word array
14 type in_addr
= Word8.word vector
16 val preInAddrToWord8Array
= fn a
=> a
17 val inAddrToWord8Vector
= fn v
=> v
19 val inAddrLen
= C_Size
.toInt Prim
.inAddrSize
22 val ia
: pre_in_addr
= Array
.array (inAddrLen
, 0wx0
: Word8.word)
23 fun finish () = Array
.vector ia
29 val (wa
, finish
) = newInAddr ()
34 val w
= Word8.castFromSysWord (C_Int
.castToSysWord acc
)
37 (wa
, (inAddrLen
- 1) - i
, w
)
39 loop (i
+ 1, C_Int
.>> (acc
, 0w4
))
42 loop (0, Prim
.INADDR_ANY
)
46 structure AddrFamily
= Net
.AddrFamily
47 type addr_family
= AddrFamily
.t
49 datatype entry
= T
of {name
: string,
51 addrType
: addr_family
,
55 fun make
s (T r
) = s r
58 val aliases
= make #aliases
59 val addrType
= make #addrType
60 val addrs
= make #addrs
62 fun addr entry
= hd (addrs entry
)
65 fun get (i
: C_Int
.t
): entry option
=
68 val name
= CUtil
.C_String
.toString (Prim
.getEntryName ())
69 val numAliases
= Prim
.getEntryAliasesNum ()
70 fun fill (n
, aliases
) =
71 if C_Int
.< (n
, numAliases
)
74 CUtil
.C_String
.toString (Prim
.getEntryAliasesN n
)
76 fill (C_Int
.+ (n
, 1), alias
::aliases
)
79 val aliases
= fill (0, [])
80 val addrType
= Prim
.getEntryAddrType ()
81 val length
= Prim
.getEntryLength ()
82 val numAddrs
= Prim
.getEntryAddrsNum ()
84 if C_Int
.< (n
, numAddrs
)
86 val addr
= Word8Array
.array (C_Int
.toInt length
, 0wx0
)
87 val _
= Prim
.getEntryAddrsN (n
, Word8Array
.toPoly addr
)
88 val addr
= Word8Vector
.toPoly (Word8Array
.vector addr
)
90 fill (C_Int
.+ (n
, 1), addr
::addrs
)
93 val addrs
= fill (0, [])
97 addrType
= AddrFamily
.fromRep addrType
,
102 fun getByAddr in_addr
=
103 get (Prim
.getByAddress (in_addr
, C_Socklen
.fromInt (Vector.length in_addr
)))
105 get (Prim
.getByName (NullString
.nullTerm name
))
111 val buf
= CharArray
.array (n
, #
"\000")
113 Posix
.Error
.SysCall
.simple
114 (fn () => Prim
.getHostName (CharArray
.toPoly buf
, C_Size
.fromInt n
))
116 case CharArray
.findi (fn (_
, c
) => c
= #
"\000") buf
of
117 NONE
=> CharArray
.vector buf
119 CharArraySlice
.vector (CharArraySlice
.slice (buf
, 0, SOME i
))
122 fun scan reader state
=
126 SOME (#
"0", state
') =>
127 (case reader state
' of
128 NONE
=> SOME (0w0
, state
')
129 |
SOME (c
, state
'') =>
131 then StringCvt.wdigits
StringCvt.OCT reader state
'
132 else if c
= #
"x" orelse c
= #
"X"
133 then StringCvt.wdigits
StringCvt.HEX reader state
''
134 else SOME (0w0
, state
'))
135 | _
=> StringCvt.wdigits
StringCvt.DEC reader state
136 fun loop (n
, state
, acc
) =
140 fun finish (w
, state
) =
142 SOME (#
".", state
') =>
143 loop (n
- 1, state
', (w
, state
)::acc
)
144 | _
=> List.rev ((w
, state
)::acc
)
147 SOME (w
, state
') => finish (w
, state
')
148 | NONE
=> List.rev acc
150 val l
= loop (4, state
, [])
152 (Word8.fromLarge (Word.toLarge (Word.andb (w
, 0wxFF
))),
168 val (a
,b
,c
,w
) = get3 w
177 val (d
,c
,b
,a
,w
) = get4 w
180 then SOME (Vector.fromList
[a
,b
,c
,d
], statew
)
183 |
[(x
, statex
), (w
, statew
)] =>
185 val (d
,c
,b
,w
) = get3 w
188 if w
= 0wx0
andalso x
= 0wx0
189 then SOME (Vector.fromList
[a
,b
,c
,d
], statew
)
190 else try
[(x
, statex
)]
192 |
[(y
, statey
), (x
, statex
), (w
, statew
)] =>
198 if w
= 0wx0
andalso x
= 0wx0
andalso y
= 0wx0
199 then SOME (Vector.fromList
[a
,b
,c
,d
], statew
)
200 else try
[(y
, statey
), (x
, statex
)]
202 |
[(z
, statez
), (y
, statey
), (x
, statex
), (w
, statew
)] =>
209 if w
= 0wx0
andalso x
= 0wx0
andalso y
= 0wx0
andalso z
= 0wx0
210 then SOME (Vector.fromList
[a
,b
,c
,d
], statew
)
211 else try
[(z
, statez
), (y
, statey
), (x
, statex
)]
218 fun fromString s
= StringCvt.scanString scan s
219 fun toString in_addr
=
220 String.concatWith
"."
221 (Vector.foldr (fn (w
,ss
) => (Word8.fmt
StringCvt.DEC w
)::ss
) [] in_addr
)