| author | wenzelm | 
| Fri, 05 May 2023 12:01:09 +0200 | |
| changeset 77967 | 6bb2f9b32804 | 
| parent 75577 | c51e1cef1eae | 
| child 78716 | 97dfba4405e3 | 
| 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 make_streams: Socket.active INetSock.stream_sock -> BinIO.instream * BinIO.outstream | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 12 | 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 | 13 | val with_streams: (BinIO.instream * BinIO.outstream -> 'a) -> string -> 'a | 
| 74143 | 14 | 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 | 15 | end; | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 16 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 17 | structure Socket_IO: SOCKET_IO = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 18 | struct | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 19 | |
| 69799 | 20 | fun close_permissive socket = | 
| 21 | Socket.close socket handle OS.SysErr _ => (); | |
| 22 | ||
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 23 | fun make_streams socket = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 24 | let | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 25 | val (host, port) = INetSock.fromAddr (Socket.Ctl.getSockName socket); | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 26 | val name = NetHostDB.toString host ^ ":" ^ string_of_int port; | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 27 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 28 | val rd = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 29 |       BinPrimIO.RD {
 | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 30 | name = name, | 
| 62354 | 31 | chunkSize = 4096, | 
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 32 | readVec = SOME (fn n => Socket.recvVec (socket, n)), | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 33 | readArr = SOME (fn buffer => Socket.recvArr (socket, buffer)), | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 34 | readVecNB = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 35 | readArrNB = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 36 | block = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 37 | canInput = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 38 | avail = fn () => NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 39 | getPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 40 | setPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 41 | endPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 42 | verifyPos = NONE, | 
| 69799 | 43 | close = fn () => close_permissive socket, | 
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 44 | ioDesc = NONE | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 45 | }; | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 46 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 47 | val wr = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 48 |       BinPrimIO.WR {
 | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 49 | name = name, | 
| 62354 | 50 | chunkSize = 4096, | 
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 51 | writeVec = SOME (fn buffer => Socket.sendVec (socket, buffer)), | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 52 | writeArr = SOME (fn buffer => Socket.sendArr (socket, buffer)), | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 53 | writeVecNB = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 54 | writeArrNB = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 55 | block = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 56 | canOutput = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 57 | getPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 58 | setPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 59 | endPos = NONE, | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 60 | verifyPos = NONE, | 
| 69799 | 61 | close = fn () => close_permissive socket, | 
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 62 | ioDesc = NONE | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 63 | }; | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 64 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 65 | val in_stream = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 66 | BinIO.mkInstream | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 67 | (BinIO.StreamIO.mkInstream (rd, Word8Vector.fromList [])); | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 68 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 69 | val out_stream = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 70 | BinIO.mkOutstream | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 71 | (BinIO.StreamIO.mkOutstream (wr, IO.BLOCK_BUF)); | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 72 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 73 | in (in_stream, out_stream) end; | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 74 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 75 | |
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 76 | fun open_streams socket_name = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 77 | let | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 78 |     fun err () = error ("Bad socket name: " ^ quote socket_name);
 | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 79 | val (host, port) = | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 80 | (case space_explode ":" socket_name of | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 81 | [h, p] => | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 82 | (case NetHostDB.getByName h of SOME host => host | NONE => err (), | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 83 | case Int.fromString p of SOME port => port | NONE => err ()) | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 84 | | _ => err ()); | 
| 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 85 | 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 | 86 | val _ = Socket.connect (socket, INetSock.toAddr (NetHostDB.addr host, port)); | 
| 74143 | 87 | in make_streams socket end | 
| 88 | handle OS.SysErr (msg, _) => error (msg ^ ": failed to open socket " ^ socket_name); | |
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 89 | |
| 69483 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 90 | fun with_streams f = | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 91 | Thread_Attributes.uninterruptible (fn restore_attributes => fn socket_name => | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 92 | let | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 93 | val streams = open_streams socket_name; | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 94 | val result = Exn.capture (restore_attributes f) streams; | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 95 | in BinIO.closeIn (#1 streams); BinIO.closeOut (#2 streams); Exn.release result end); | 
| 
023d92df3d84
more robust open/close bracket, but with potential danger of blocking indefinitely in uninterruptible state;
 wenzelm parents: 
69124diff
changeset | 96 | |
| 74143 | 97 | fun with_streams' f socket_name password = | 
| 98 | with_streams (fn streams => | |
| 75577 
c51e1cef1eae
more scalable byte messages, notably for Scala functions in ML;
 wenzelm parents: 
74143diff
changeset | 99 | (Byte_Message.write_line (#2 streams) (Bytes.string password); f streams)) socket_name; | 
| 74143 | 100 | |
| 50800 
c0fb2839d1a9
recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
 wenzelm parents: diff
changeset | 101 | end; |