author | wenzelm |
Thu, 02 Jan 2025 16:59:42 +0100 | |
changeset 81710 | c914db7419a3 |
parent 79056 | 1f34f6394383 |
permissions | -rw-r--r-- |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
1 |
(* Title: Pure/General/socket_io.ML |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
2 |
Author: Timothy Bourke, NICTA |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
3 |
Author: Makarius |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
4 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
5 |
Stream IO over TCP sockets. Following example 10.2 in "The Standard |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
6 |
ML Basis Library" by Emden R. Gansner and John H. Reppy. |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
7 |
*) |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
8 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
9 |
signature SOCKET_IO = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
10 |
sig |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
11 |
val open_streams: string -> BinIO.instream * BinIO.outstream |
69483
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
wenzelm
parents:
69124
diff
changeset
|
12 |
val with_streams: (BinIO.instream * BinIO.outstream -> 'a) -> string -> 'a |
74143 | 13 |
val with_streams': (BinIO.instream * BinIO.outstream -> 'a) -> string -> string -> 'a |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
14 |
end; |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
15 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
16 |
structure Socket_IO: SOCKET_IO = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
17 |
struct |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
18 |
|
69799 | 19 |
fun close_permissive socket = |
20 |
Socket.close socket handle OS.SysErr _ => (); |
|
21 |
||
79056
1f34f6394383
more uniform buffer_size (see also c83cdd300848 and 26c790a6ce43);
wenzelm
parents:
79049
diff
changeset
|
22 |
val buffer_size = 65536; |
1f34f6394383
more uniform buffer_size (see also c83cdd300848 and 26c790a6ce43);
wenzelm
parents:
79049
diff
changeset
|
23 |
|
79047 | 24 |
fun make_streams socket_name socket = |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
25 |
let |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
26 |
val rd = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
27 |
BinPrimIO.RD { |
79046 | 28 |
name = socket_name, |
79056
1f34f6394383
more uniform buffer_size (see also c83cdd300848 and 26c790a6ce43);
wenzelm
parents:
79049
diff
changeset
|
29 |
chunkSize = buffer_size, |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
30 |
readVec = SOME (fn n => Socket.recvVec (socket, n)), |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
31 |
readArr = SOME (fn buffer => Socket.recvArr (socket, buffer)), |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
32 |
readVecNB = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
33 |
readArrNB = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
34 |
block = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
35 |
canInput = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
36 |
avail = fn () => NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
37 |
getPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
38 |
setPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
39 |
endPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
40 |
verifyPos = NONE, |
69799 | 41 |
close = fn () => close_permissive socket, |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
42 |
ioDesc = NONE |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
43 |
}; |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
44 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
45 |
val wr = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
46 |
BinPrimIO.WR { |
79046 | 47 |
name = socket_name, |
79056
1f34f6394383
more uniform buffer_size (see also c83cdd300848 and 26c790a6ce43);
wenzelm
parents:
79049
diff
changeset
|
48 |
chunkSize = buffer_size, |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
49 |
writeVec = SOME (fn buffer => Socket.sendVec (socket, buffer)), |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
50 |
writeArr = SOME (fn buffer => Socket.sendArr (socket, buffer)), |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
51 |
writeVecNB = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
52 |
writeArrNB = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
53 |
block = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
54 |
canOutput = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
55 |
getPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
56 |
setPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
57 |
endPos = NONE, |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
58 |
verifyPos = NONE, |
69799 | 59 |
close = fn () => close_permissive socket, |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
60 |
ioDesc = NONE |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
61 |
}; |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
62 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
63 |
val in_stream = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
64 |
BinIO.mkInstream |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
65 |
(BinIO.StreamIO.mkInstream (rd, Word8Vector.fromList [])); |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
66 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
67 |
val out_stream = |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
68 |
BinIO.mkOutstream |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
69 |
(BinIO.StreamIO.mkOutstream (wr, IO.BLOCK_BUF)); |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
70 |
|
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
71 |
in (in_stream, out_stream) end; |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
72 |
|
79049
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
73 |
fun socket_name_inet name = |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
74 |
(case space_explode ":" name of |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
75 |
[h, p] => |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
76 |
(case (NetHostDB.getByName h, Int.fromString p) of |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
77 |
(SOME host, SOME port) => SOME (host, port) |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
78 |
| _ => NONE) |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
79 |
| _ => NONE); |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
80 |
|
79049
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
81 |
fun open_streams_inet (host, port) = |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
82 |
let |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
83 |
val socket: Socket.active INetSock.stream_sock = INetSock.TCP.socket (); |
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
84 |
val _ = Socket.connect (socket, INetSock.toAddr (NetHostDB.addr host, port)); |
79047 | 85 |
|
86 |
val (socket_host, socket_port) = INetSock.fromAddr (Socket.Ctl.getSockName socket); |
|
87 |
val socket_name = NetHostDB.toString socket_host ^ ":" ^ string_of_int socket_port; |
|
79049
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
88 |
in make_streams socket_name socket end; |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
89 |
|
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
90 |
fun open_streams_unix path = |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
91 |
\<^if_windows>\<open>raise Fail "Cannot create Unix-domain socket on Windows"\<close> |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
92 |
\<^if_unix>\<open> |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
93 |
let |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
94 |
val socket_name = File.platform_path path; |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
95 |
val socket: Socket.active UnixSock.stream_sock = UnixSock.Strm.socket (); |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
96 |
val _ = Socket.connect (socket, UnixSock.toAddr socket_name); |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
97 |
in make_streams socket_name socket end\<close> |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
98 |
|
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
99 |
fun open_streams name = |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
100 |
(case socket_name_inet name of |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
101 |
SOME inet => open_streams_inet inet |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
102 |
| NONE => |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
103 |
(case try Path.explode name of |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
104 |
SOME path => open_streams_unix path |
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
wenzelm
parents:
79047
diff
changeset
|
105 |
| NONE => error ("Bad socket name: " ^ quote name))) |
79046 | 106 |
handle OS.SysErr (msg, _) => error (msg ^ ": failed to open socket " ^ name); |
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
107 |
|
69483
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
wenzelm
parents:
69124
diff
changeset
|
108 |
fun with_streams f = |
79046 | 109 |
Thread_Attributes.uninterruptible (fn run => fn name => |
69483
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
wenzelm
parents:
69124
diff
changeset
|
110 |
let |
79046 | 111 |
val streams = open_streams name; |
78716 | 112 |
val result = Exn.capture (run f) streams; |
78718 | 113 |
val _ = BinIO.closeIn (#1 streams); |
114 |
val _ = BinIO.closeOut (#2 streams); |
|
115 |
in Exn.release result end); |
|
69483
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
wenzelm
parents:
69124
diff
changeset
|
116 |
|
79046 | 117 |
fun with_streams' f name password = |
74143 | 118 |
with_streams (fn streams => |
79046 | 119 |
(Byte_Message.write_line (#2 streams) (Bytes.string password); f streams)) name; |
74143 | 120 |
|
50800
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff
changeset
|
121 |
end; |