| author | wenzelm | 
| Fri, 28 Jun 2024 13:20:18 +0200 | |
| changeset 80443 | ab0dd21dd0ca | 
| 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: 
69124diff
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: 
79049diff
changeset | 22 | val buffer_size = 65536; | 
| 
1f34f6394383
more uniform buffer_size (see also c83cdd300848 and 26c790a6ce43);
 wenzelm parents: 
79049diff
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: 
79049diff
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: 
79049diff
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: 
79047diff
changeset | 73 | fun socket_name_inet name = | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 74 | (case space_explode ":" name of | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 75 | [h, p] => | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 76 | (case (NetHostDB.getByName h, Int.fromString p) of | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 77 | (SOME host, SOME port) => SOME (host, port) | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 78 | | _ => NONE) | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
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: 
79047diff
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: 
79047diff
changeset | 88 | in make_streams socket_name socket end; | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 89 | |
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 90 | fun open_streams_unix path = | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
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: 
79047diff
changeset | 92 | \<^if_unix>\<open> | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 93 | let | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 94 | val socket_name = File.platform_path path; | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
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: 
79047diff
changeset | 96 | val _ = Socket.connect (socket, UnixSock.toAddr socket_name); | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 97 | in make_streams socket_name socket end\<close> | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 98 | |
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 99 | fun open_streams name = | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 100 | (case socket_name_inet name of | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 101 | SOME inet => open_streams_inet inet | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 102 | | NONE => | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 103 | (case try Path.explode name of | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
changeset | 104 | SOME path => open_streams_unix path | 
| 
10b6add456d0
support for Unix-domain sockets, using java.nio.channels.ServerSocketChannel;
 wenzelm parents: 
79047diff
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: 
69124diff
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: 
69124diff
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: 
69124diff
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; |