|
1 (* Title: Tools/WWW_Find/socket_util.ML |
|
2 Author: Timothy Bourke, NICTA |
|
3 |
|
4 Routines for working with sockets. Following example 10.2 in "The |
|
5 Standard-ML Basis Library" by Emden R. Gansner and John H. Reppy. |
|
6 *) |
|
7 |
|
8 signature SOCKET_UTIL = |
|
9 sig |
|
10 val init_server_socket: string option -> int -> Socket.passive INetSock.stream_sock |
|
11 val make_streams: Socket.active INetSock.stream_sock -> BinIO.instream * BinIO.outstream |
|
12 end; |
|
13 |
|
14 structure Socket_Util: SOCKET_UTIL = |
|
15 struct |
|
16 |
|
17 fun init_server_socket opt_host port = |
|
18 let |
|
19 val sock = INetSock.TCP.socket (); |
|
20 val addr = |
|
21 (case opt_host of |
|
22 NONE => INetSock.any port |
|
23 | SOME host => |
|
24 NetHostDB.getByName host |
|
25 |> the |
|
26 |> NetHostDB.addr |
|
27 |> rpair port |
|
28 |> INetSock.toAddr |
|
29 handle Option => raise Fail ("Cannot resolve hostname: " ^ host)); |
|
30 val _ = Socket.bind (sock, addr); |
|
31 val _ = Socket.listen (sock, 5); |
|
32 in sock end; |
|
33 |
|
34 fun make_streams sock = |
|
35 let |
|
36 val (haddr, port) = INetSock.fromAddr (Socket.Ctl.getSockName sock); |
|
37 |
|
38 val sock_name = |
|
39 implode [ NetHostDB.toString haddr, ":", string_of_int port ]; |
|
40 |
|
41 val rd = |
|
42 BinPrimIO.RD { |
|
43 name = sock_name, |
|
44 chunkSize = Socket.Ctl.getRCVBUF sock, |
|
45 readVec = SOME (fn sz => Socket.recvVec (sock, sz)), |
|
46 readArr = SOME (fn buffer => Socket.recvArr (sock, buffer)), |
|
47 readVecNB = NONE, |
|
48 readArrNB = NONE, |
|
49 block = NONE, |
|
50 canInput = NONE, |
|
51 avail = fn () => NONE, |
|
52 getPos = NONE, |
|
53 setPos = NONE, |
|
54 endPos = NONE, |
|
55 verifyPos = NONE, |
|
56 close = fn () => Socket.close sock, |
|
57 ioDesc = NONE |
|
58 }; |
|
59 |
|
60 val wr = |
|
61 BinPrimIO.WR { |
|
62 name = sock_name, |
|
63 chunkSize = Socket.Ctl.getSNDBUF sock, |
|
64 writeVec = SOME (fn buffer => Socket.sendVec (sock, buffer)), |
|
65 writeArr = SOME (fn buffer => Socket.sendArr (sock, buffer)), |
|
66 writeVecNB = NONE, |
|
67 writeArrNB = NONE, |
|
68 block = NONE, |
|
69 canOutput = NONE, |
|
70 getPos = NONE, |
|
71 setPos = NONE, |
|
72 endPos = NONE, |
|
73 verifyPos = NONE, |
|
74 close = fn () => Socket.close sock, |
|
75 ioDesc = NONE |
|
76 }; |
|
77 |
|
78 val in_strm = |
|
79 BinIO.mkInstream ( |
|
80 BinIO.StreamIO.mkInstream (rd, Word8Vector.fromList [])); |
|
81 |
|
82 val out_strm = |
|
83 BinIO.mkOutstream ( |
|
84 BinIO.StreamIO.mkOutstream (wr, IO.BLOCK_BUF)); |
|
85 |
|
86 in (in_strm, out_strm) end; |
|
87 |
|
88 end; |
|
89 |