3 <ENTRY GET-HOST GET-SERVICE GET-PROTOCOL GET-ADDR
4 NO-BLOCK? INTERRUPT? CONNECTION-LOST CONNECTION-READY
5 CONNECTION-URGENT CHAN-SELECT SEND RECEIVE NET-SERVER
6 SERVER-INIT SERVER-WAIT
7 GET-ADDRESS LISTEN-ON-DATA CONNECT-DATA-CHANNEL
8 GET-DATA-ADDRESS WRAP-SOCKET>
12 <INCLUDE-WHEN <COMPILING? "NETWORK"> "NETDEFS">
16 <ADD-CHANNEL-OPS NETWORK
17 READ-SAFE-BUFFER NETWORK-READ-SAFE
18 GET-HOST NETWORK-GET ;"DONE"
19 GET-SERVICE NETWORK-GET ;"DONE"
20 GET-PROTOCOL NETWORK-GET ;"DONE"
21 GET-ADDR NETWORK-GET ;"DONE"
23 INTERRUPT? NETWORK-SET
25 RECEIVE NETWORK-RECEIVE
26 GET-ADDRESS NET-GET-ADDRESS
27 LISTEN-ON-DATA NET-MAKE-ALT
28 CONNECT-DATA-CHANNEL NET-ACCEPT-CONN
29 GET-DATA-ADDRESS NET-GET-DADDR>
31 <DEFINE NETWORK-SEND (CHANNEL:<CHANNEL 'NETWORK> OPER BUF:<OR STRING UVECTOR>
32 "OPT" (LEN:FIX <COND (<TYPE? .BUF UVECTOR> <LENGTH .BUF>)
34 "AUX" (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>)
35 (FLAG:FIX 0) RES:<OR FIX FALSE>)
36 <COND (<N==? <LHW <C-SERVICE .DATA>> ,PROT-UDP>
40 <CALL SYSCALL SEND <C-SOCKET .DATA> .BUF
41 <COND (<TYPE? .BUF UVECTOR> <* 4 .LEN>) (T .LEN)> .FLAG>>
42 <COND (<TYPE? .BUF UVECTOR> </ .RES 4>)
45 <DEFINE NETWORK-RECEIVE (CHANNEL:<CHANNEL 'NETWORK> OPER BUF:<OR UVECTOR STRING>
46 "OPT" (LEN:FIX <COND (<TYPE? .BUF STRING>
49 "AUX" (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>)
50 (FLAG:FIX 0) RES:<OR FIX FALSE>)
51 <COND (<N==? <LHW <C-SERVICE .DATA>> ,PROT-UDP>
54 (<OR <NOT <C-TIMEOUT .DATA>>
57 (<SET RES <ISYSCALL RECV <C-SOCKET .DATA> .BUF
58 <COND (<TYPE? .BUF UVECTOR> <* 4 .LEN>)(T .LEN)>
60 <COND (<TYPE? .BUF UVECTOR> </ .RES 4>)
63 <DEFINE NETWORK-SET (CHANNEL:<CHANNEL 'NETWORK> OPER:ATOM "OPT" NEW:<OR ATOM FALSE>
64 "AUX" (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>)
66 <COND (<==? .OPER INTERRUPT?>
68 (<==? .OPER NO-BLOCK?>
71 (<NOT <ASSIGNED? NEW>>
72 <NOT <0? <ANDB .FLAG <C-FLAGS .DATA>>>>)
74 <C-FLAGS .DATA <ORB .FLAG <C-FLAGS .DATA>>>
75 <PROG ((CURRENT-CONNECTION:<SPECIAL <CHANNEL 'NETWORK>> .CHANNEL))
77 (<CALL SYSCALL FCNTL <C-SOCKET .DATA> ,F-SETFL <C-FLAGS .DATA>>
80 <DEFINE WRAP-SOCKET (S:FIX
81 "AUX" (ADDR:NET-ADDRESS
82 <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN>>
83 NET-ADDRESS>) (TUV <STACK <IUVECTOR 1>>))
84 <COND (<CALL SYSCALL GETSOCKNAME .S .ADDR .TUV>
85 <CHANNEL-OPEN NETWORK "RAND" 0 .ADDR .S>)>>
87 <DEFINE NETWORK-READ-SAFE (CHANNEL:<CHANNEL 'NETWORK> OPER
89 "AUX" (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>)
90 (BUF:UVECTOR <STACK <IUVECTOR 1>>)
92 (CURRENT-CONNECTION:<SPECIAL <CHANNEL 'NETWORK>>
94 #DECL ((STUFF) <<PRIMTYPE VECTOR>
95 [REST <OR STRING UVECTOR>
97 <COND (<OR <NETWORK-SET .CHANNEL NO-BLOCK?>
98 <AND <SET RES <CALL SYSCALL IOCTL
99 <C-SOCKET .DATA> ,FIONREAD .BUF>>
101 <NETWORK-READ .CHANNEL .OPER !.STUFF>)
104 <DEFINE NETWORK-GET (CHANNEL:<CHANNEL 'NETWORK> OPER:ATOM
105 "AUX" (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>)
106 (ADDR <C-ADDR .DATA>))
107 <COND (<==? .OPER GET-HOST>
109 (<==? .OPER GET-SERVICE>
111 (<==? .OPER GET-ADDR>
113 (<==? .OPER GET-PROTOCOL>
114 <LHW <C-SERVICE .DATA>>)>>
116 <DEFINE NET-PIPE-HANDLER (IGN "AUX" CHN)
117 <COND (<AND <ASSIGNED? CURRENT-CONNECTION>
118 <SET CHN .CURRENT-CONNECTION>>
119 <KILL-CHANNEL .CHN>)>
120 <COND (<NETWORK-SET .CHN INTERRUPT?>
121 <INTERRUPT "NETWORK" .CHN CONNECTION-LOST>)>>
123 <DEFINE NET-SIGIO-HANDLER (IGN "AUX" (RBUF:UVECTOR <STACK <IUVECTOR 1>>)
124 (EBUF:UVECTOR <STACK <IUVECTOR 1>>) (RFL:FIX 0)
125 (EFL:FIX 0) (MAX:FIX -1) FOUND:<OR FALSE FIX>)
126 <REPEAT ((L:<LIST [REST FIX CHANNEL]> ,NET-CHANNELS) S)
127 <COND (<EMPTY? .L> <RETURN>)>
128 <SET EFL <ORB .EFL <LSH 1 <SET S <1 .L>>>>>
129 <SET RFL <ORB .RFL <LSH 1 .S>>>
130 <SET MAX <MAX .MAX .S>>>
135 (<SET FOUND <CALL SYSCALL SELECT <+ .MAX 1> .RBUF 0 .EBUF>>
136 <POKE .EBUF CONNECTION-URGENT .MAX>
137 <POKE .RBUF CONNECTION-READY .MAX>)>)>>
139 <DEFINE POKE (BUF:<UVECTOR [REST FIX]> WHICH MAX:FIX
140 "AUX" (L:<LIST [REST FIX <CHANNEL 'NETWORK>]> ,NET-CHANNELS))
141 <REPEAT ((CUR 0) (BITS <1 .BUF>) NL:<OR LIST FALSE>)
143 (<NOT <0? <ANDB .BITS <LSH 1 .CUR>>>>
145 (<SET NL <MEMQ .CUR ,NET-CHANNELS>>
146 <INTERRUPT "NETWORK" <2 .NL> .WHICH>)>)>
147 <COND (<G? <SET CUR <+ .CUR 1>> .MAX>
150 <DEFINE CHAN-SELECT (TIMEOUT:<OR FIX FLOAT FALSE>
152 "AUX" (RBUF <STACK <IUVECTOR 1>>)
153 (EBUF <STACK <IUVECTOR 1>>) (RFL 0)
154 (TIMEVAL <STACK <IUVECTOR 2>>)
155 (HANDLES <STACK <IUVECTOR </ <LENGTH .STUFF> 2> -1>>)
157 #DECL ((STUFF) <<PRIMTYPE VECTOR>
158 [REST <CHANNEL 'NETWORK> <OR APPLICABLE FALSE>]>)
160 <TIME-NUM .TIMEVAL .TIMEOUT>)>
161 <REPEAT (CHN:<CHANNEL 'NETWORK> (TST .STUFF) H:FIX (HAND .HANDLES))
162 <COND (<EMPTY? .TST> <RETURN>)>
163 <COND (<SET H <CHANNEL-OP <1 .TST> FILE-HANDLE>>
165 <SET MAX <MAX .H .MAX>>
166 <SET RFL <ORB .RFL <LSH 1 .H>>>)>
167 <SET TST <REST .TST 2>>
168 <SET HAND <REST .HAND>>>
174 <COND (<SET RES <ISYSCALL SELECT <+ .MAX 1> .RBUF 0 .EBUF
175 <COND (.TIMEOUT .TIMEVAL) (T 0)>>>
176 <COND (<INVOKE <ORB <1 .RBUF> <1 .EBUF>> .STUFF .HANDLES .MAX>
181 <DEFINE INVOKE (BITS:FIX STUFF:<<PRIMTYPE VECTOR> [REST <CHANNEL 'NETWORK>
182 <OR APPLICABLE FALSE>]>
183 HANDLES:<UVECTOR [REST FIX]> MAX:FIX
185 <REPEAT (HH:UVECTOR TS:<PRIMTYPE VECTOR>)
186 <COND (<NOT <0? <ANDB <LSH 1 .CUR> .BITS>>>
187 <SET HH <MEMQ .CUR .HANDLES>>
188 <SET TS <REST .STUFF <* 2 <- <LENGTH .HANDLES> <LENGTH .HH>>>>>
189 <COND (<NOT <2 .TS>> <RETURN>)>
190 <APPLY <2 .TS> <1 .TS>>)>
191 <COND (<G? <SET CUR <+ .CUR 1>> .MAX> <RETURN <>>)>>>
193 <COND (<GASSIGNED? NET-PIPE-HANDLER>
194 <ON <HANDLER "PIPE" ,NET-PIPE-HANDLER>>)>
196 <COND (<GASSIGNED? NET-SIGIO-HANDLER>
197 <ON <HANDLER "IOINT" ,NET-SIGIO-HANDLER>>
198 <ON <HANDLER "SOCKET" ,NET-SIGIO-HANDLER>>)>
201 <DEFINE SERVER-WAIT (S:FIX "OPT" (TIMEOUT:<OR FIX FLOAT FALSE> <>)
202 (ADDR:NET-ADDRESS <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN>>
204 "AUX" NS (BUF <STACK <IUVECTOR 1>>) RS
205 (TO <STACK <IUVECTOR 2>>) RES
206 (PT <STACK <UVECTOR ,ADDR-LEN>>))
208 <TIME-NUM .TO .TIMEOUT>)
214 <ISYSCALL SELECT <+ .RS 1> .BUF 0 0 .TO>:<OR FIX FALSE>>
215 <COND (<0? .RES> ,TIMED-OUT)
217 <COND (<==? <LHW .S> ,SOCK-STREAM>
218 <COND (<SET S <ISYSCALL ACCEPT .RS .ADDR .PT>>
219 <CHANNEL-OPEN NETWORK "SERVER" 0
222 <ERROR NOT-SUPPORTED .S SERVER-WAIT>)>)>)>>
224 <DEFINE SERVER-INIT (SERVICE:FIX "OPT" (HOST:FIX 0)
225 "AUX" (PROT <LHW .SERVICE>)
226 (SERVSOCK <RHW .SERVICE>) KIND S ERR
227 (ADDR <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN>>
229 <COND (<==? .PROT ,PROT-UDP> <SET KIND ,SOCK-DGRAM>)
230 (T <SET KIND ,SOCK-STREAM>)>
231 <COND (<SET S <CALL SYSCALL SOCKET ,AF-INET .KIND .PROT>>
232 <BUILD-ADDRESS .SERVICE .HOST .ADDR>
234 (<==? .KIND ,SOCK-STREAM>
235 <COND (<AND <SET ERR <CALL SYSCALL BIND .S .ADDR ,ADDR-LEN>>
236 <SET ERR <CALL SYSCALL LISTEN .S 5>>>
239 <CALL SYSCALL CLOSE .S>
242 <COND (<SET ERR <CALL SYSCALL BIND .S .ADDR ,ADDR-LEN>>
245 <CALL SYSCALL CLOSE .S>
248 <DEFINE NET-SERVER (SERVICE:FIX ROUTINE:APPLICABLE "OPTIONAL" (H:FIX 0)
251 (NADDR <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN>>
253 (PT <STACK <IUVECTOR 1>>))
254 #DECL ((SERVICE H) FIX)
255 <COND (<SET S <SERVER-INIT .SERVICE .H>>
256 <COND (<==? <LHW .S> ,SOCK-STREAM>
258 <COND (<SET CH <SERVER-WAIT .S <> .NADDR>>
259 <APPLY .ROUTINE .CH>)
261 <CALL SYSCALL CLOSE .S>
264 <COND (<NOT <GASSIGNED? MSG-BUF>>
265 <SETG MSG-BUF <ISTRING 512>>)>
268 <COND (<SET LEN <ISYSCALL RECVFROM .S ,MSG-BUF 512
270 <APPLY .ROUTINE ,MSG-BUF .LEN .NADDR .PT>)
272 <CALL SYSCALL CLOSE .S>
273 <RETURN .LEN>)>>)>)>>
275 <GDECL (MSG-BUF) STRING>
277 <DEFINE NET-GET-ADDRESS (CHANNEL:<CHANNEL 'NETWORK> OPER
278 "OPT" (ADDR:<OR NET-ADDRESS FALSE> <>) "AUX"
279 (DATA:CONNECTION <CHANNEL-DATA .CHANNEL>))
280 <GET-ADDRESS <C-SOCKET .DATA> .ADDR>>
282 <DEFINE GET-ADDRESS (SOCK:FIX "OPT" (ADDR:<OR NET-ADDRESS FALSE> <>)
283 "AUX" (TBUF <STACK <UVECTOR ,ADDR-LEN>>))
284 <COND (<NOT .ADDR> <SET ADDR <CHTYPE <IUVECTOR ,ADDR-WORD-LEN 0>
286 <CALL SYSCALL GETSOCKNAME .SOCK .ADDR .TBUF>
289 <DEFINE NET-MAKE-ALT (C:<CHANNEL 'NETWORK> OPER
290 "OPT" (TYPE:FIX ,SOCK-STREAM) (PORT 0)
291 "AUX" S RES NC (DATA:CONNECTION <CHANNEL-DATA .C>)
292 (ADDR <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN 0>>
294 <COND (<C-ALTCHANNEL .DATA>)
295 (<SET S <CALL SYSCALL SOCKET ,AF-INET
297 <COND (<==? .TYPE ,SOCK-STREAM> ,PROT-TCP)
299 <CHANNEL-OP .C GET-ADDRESS .ADDR>
300 <IN-ADDR-PORT .ADDR .PORT>
301 <COND (<SET RES <CALL SYSCALL BIND .S .ADDR ,ADDR-LEN>>
302 <COND (<SET RES <CALL SYSCALL LISTEN .S 1>>
303 <C-ALTCHANNEL .DATA .S>
306 <CALL SYSCALL CLOSE .S>
309 <CALL SYSCALL CLOSE .S>
312 <DEFINE NET-GET-DADDR (C:<CHANNEL 'NETWORK> OPER
313 "OPT" (ADDR:<OR NET-ADDRESS FALSE> <>)
314 "AUX" (DATA:CONNECTION <CHANNEL-DATA .C>) NC)
315 <COND (<SET NC <C-ALTCHANNEL .DATA>>
316 <COND (<TYPE? .NC FIX>
317 <GET-ADDRESS .NC .ADDR>)
319 <CHANNEL-OP .NC GET-ADDRESS .ADDR>)>)>>
321 <DEFINE NET-ACCEPT-CONN (C:<CHANNEL 'NETWORK> OPER "OPT" (SERVICE:FIX 0)
322 "AUX" (DATA:CONNECTION <CHANNEL-DATA .C>) NC
324 <CHTYPE <STACK <IUVECTOR ,ADDR-WORD-LEN 0>>
325 NET-ADDRESS>) (BUF <STACK <IUVECTOR 1>>)
326 (PT:UVECTOR <STACK <IUVECTOR 1>>) RES:<OR FIX FALSE>
327 NS:<OR FIX FALSE> CH)
328 <COND (<TYPE? <SET NC <C-ALTCHANNEL .DATA>> FIX>
329 <COND (<OR <NOT <C-TIMEOUT .DATA>>
330 <AND <SET RES <ISYSCALL SELECT <+ .NC 1>
331 <1 .BUF <LSH 1 .NC>> 0 0
334 <COND (<SET NS <ISYSCALL ACCEPT .NC .NADDR .PT>>
335 <SET CH <CHANNEL-OPEN NETWORK "DATA" .SERVICE .NADDR .NS>>
336 <C-ALTCHANNEL .DATA .CH>)>
337 <CALL SYSCALL CLOSE .NC>
339 (<0? .RES> ,TIMED-OUT)
341 (.NC #FALSE ("ALREADY CONNECTED"))
342 (T #FALSE ("NOT LISTENING"))>>