This source file includes following definitions.
- sk_show_nunits
- sk_set_nunits
- skc_show_device_name
- skc_set_device_name
- sk_reset
- sk_init
- set_error_str
- set_error
- skt_socket
- skt_gethostbyname
- skt_bind
- skt_listen
- skt_accept
- skt_close
- skt_read8
- skt_write8
- get_ddcw
- sk_cmd
- skc_iom_cmd
- do_try_accept
- do_try_read
- sk_process_event
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #include <netdb.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27
28 #if defined(__sun__) || defined(_AIX)
29 # include <strings.h>
30 #endif
31
32 #include "dps8.h"
33 #include "dps8_sys.h"
34 #include "dps8_faults.h"
35 #include "dps8_iom.h"
36 #include "dps8_socket_dev.h"
37 #include "dps8_cable.h"
38 #include "dps8_cpu.h"
39 #include "dps8_utils.h"
40
41 #define DBG_CTR 1
42
43 #ifndef bzero
44 # define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
45 #endif
46
47 static struct {
48 const char *name;
49 int code;
50 } errnos[] = {
51 {" ", 0},
52 #include "errnos.h"
53 };
54 #define N_ERRNOS (sizeof (errnos) / sizeof (errnos[0]))
55
56 #ifdef WITH_SOCKET_DEV
57 # define SKC_UNIT_IDX(uptr) ((uptr) - sk_unit)
58
59 struct skc_state_s
60 {
61 char device_name [MAX_DEV_NAME_LEN];
62 };
63 static struct skc_state_s skc_state[N_SKC_UNITS_MAX];
64
65 # define N_FDS 1024
66
67 static struct
68 {
69 int fd_unit[N_FDS];
70 word6 fd_dev_code[N_FDS];
71 bool fd_nonblock[N_FDS];
72 struct
73 {
74 enum
75 {
76 unit_idle = 0,
77 unit_accept,
78 unit_read
79 } unit_state;
80
81 int accept_fd;
82 int read_fd;
83 uint read_buffer_sz;
84 uint words_processed;
85 } unit_data[N_SKC_UNITS_MAX][N_DEV_CODES];
86 } sk_data;
87
88 # define N_SKC_UNITS 64
89
90 static t_stat sk_show_nunits (UNUSED FILE * st, UNUSED UNIT * uptr,
91 UNUSED int val, UNUSED const void * desc)
92 {
93 sim_printf("Number of socket units in system is %d\n", skc_dev.numunits);
94 return SCPE_OK;
95 }
96
97 static t_stat sk_set_nunits (UNUSED UNIT * uptr, UNUSED int32 value,
98 const char * cptr, UNUSED void * desc)
99 {
100 if (! cptr)
101 return SCPE_ARG;
102 int n = atoi (cptr);
103 if (n < 1 || n > N_SKC_UNITS_MAX)
104 return SCPE_ARG;
105 skc_dev.numunits = (uint32) n;
106 return SCPE_OK;
107 }
108
109 static t_stat skc_show_device_name (UNUSED FILE * st, UNIT * uptr,
110 UNUSED int val, UNUSED const void * desc)
111 {
112 int n = (int) SKC_UNIT_IDX (uptr);
113 if (n < 0 || n >= N_SKC_UNITS_MAX)
114 return SCPE_ARG;
115 if (skc_state[n].device_name[1] != 0)
116 sim_printf("Name: %s", skc_state[n].device_name);
117 return SCPE_OK;
118 }
119
120 static t_stat skc_set_device_name (UNIT * uptr, UNUSED int32 value,
121 const char * cptr, UNUSED void * desc)
122 {
123 int n = (int) SKC_UNIT_IDX (uptr);
124 if (n < 0 || n >= N_SKC_UNITS_MAX)
125 return SCPE_ARG;
126 if (cptr)
127 {
128 strncpy (skc_state[n].device_name, cptr, MAX_DEV_NAME_LEN-1);
129 skc_state[n].device_name[MAX_DEV_NAME_LEN-1] = 0;
130 }
131 else
132 skc_state[n].device_name[0] = 0;
133 return SCPE_OK;
134 }
135
136 static MTAB sk_mod [] =
137 {
138 {
139 MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_VALR,
140 0,
141 "NUNITS",
142 "NUNITS",
143 sk_set_nunits,
144 sk_show_nunits,
145 "Number of socket units in the system",
146 NULL
147 },
148 {
149 MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC,
150 0,
151 "NAME",
152 "NAME",
153 skc_set_device_name,
154 skc_show_device_name,
155 "Set the device name",
156 NULL
157 },
158 MTAB_eol
159 };
160
161 UNIT sk_unit [N_SKC_UNITS_MAX] = {
162 # ifdef NO_C_ELLIPSIS
163 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
164 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
165 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
166 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
167 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
168 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
169 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
170 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
171 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
172 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
173 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
174 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
175 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
176 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
177 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
178 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
179 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
180 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
181 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
182 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
183 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
184 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
185 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
186 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
187 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
188 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
189 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
190 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
191 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
192 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
193 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
194 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
195 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
196 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
197 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
198 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
199 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
200 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
201 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
202 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
203 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
204 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
205 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
206 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
207 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
208 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
209 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
210 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
211 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
212 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
213 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
214 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
215 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
216 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
217 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
218 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
219 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
220 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
221 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
222 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
223 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
224 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
225 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL },
226 { UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
227 # else
228 [0 ... (N_SKC_UNITS_MAX -1)] = {
229 UDATA ( NULL, 0, 0), 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL
230 },
231 # endif
232 };
233
234 static DEBTAB sk_dt [] =
235 {
236 { "NOTIFY", DBG_NOTIFY, NULL },
237 { "INFO", DBG_INFO, NULL },
238 { "ERR", DBG_ERR, NULL },
239 { "WARN", DBG_WARN, NULL },
240 { "DEBUG", DBG_DEBUG, NULL },
241 { "ALL", DBG_ALL, NULL },
242 { NULL, 0, NULL }
243 };
244
245 static t_stat sk_reset (UNUSED DEVICE * dptr)
246 {
247 return SCPE_OK;
248 }
249
250 DEVICE skc_dev = {
251 "SKC",
252 sk_unit,
253 NULL,
254 sk_mod,
255 N_SKC_UNITS,
256 10,
257 31,
258 1,
259 8,
260 9,
261 NULL,
262 NULL,
263 sk_reset,
264 NULL,
265 NULL,
266 NULL,
267 NULL,
268 DEV_DEBUG,
269 0,
270 sk_dt,
271 NULL,
272 NULL,
273 NULL,
274 NULL,
275 NULL,
276 NULL,
277 NULL
278 };
279
280 void sk_init(void)
281 {
282
283 memset(& sk_data, 0, sizeof(sk_data));
284 for (uint i = 0; i < N_FDS; i ++)
285 sk_data.fd_unit[i] = -1;
286
287
288
289 }
290
291 static void set_error_str (word36 * error_str, const char * str)
292 {
293 char work [8];
294
295
296 for (uint i = 0; i < 8; i ++)
297 work[i] = ' ';
298 size_t l = strlen (str);
299 if (l > 8)
300 l = 8;
301 for (uint i = 0; i < l; i ++)
302 work[i] = str[i];
303 error_str[0] = 0;
304 error_str[1] = 0;
305 putbits36_8 (error_str + 0, 1, (word8) work [0]);
306 putbits36_8 (error_str + 0, 10, (word8) work [1]);
307 putbits36_8 (error_str + 0, 19, (word8) work [2]);
308 putbits36_8 (error_str + 0, 28, (word8) work [3]);
309 putbits36_8 (error_str + 1, 1, (word8) work [4]);
310 putbits36_8 (error_str + 1, 10, (word8) work [5]);
311 putbits36_8 (error_str + 1, 19, (word8) work [6]);
312 putbits36_8 (error_str + 1, 28, (word8) work [7]);
313 }
314
315 static void set_error (word36 * error_str, int _errno)
316 {
317 if (errno == 0)
318 return;
319 for (uint i = 0; i < N_ERRNOS; i ++)
320 {
321 if (errnos[i].code == _errno)
322 {
323 set_error_str (error_str, errnos[i].name);
324 return;
325 }
326 }
327 char huh [256];
328 sprintf (huh, "E%d", _errno);
329 huh[8] = 0;
330 set_error_str (error_str, huh);
331 }
332
333 static void skt_socket (uint unit_idx, word5 dev_code, word36 * buffer)
334 {
335
336
337
338
339
340
341
342
343 int domain = (int) buffer[0];
344 int type = (int) buffer[1];
345 int protocol = (int) buffer[2];
346
347 sim_printf ("socket() domain %d\n", domain);
348 sim_printf ("socket() type %d\n", type);
349 sim_printf ("socket() protocol %d\n", protocol);
350
351 int _errno = 0;
352 int fd = -1;
353
354 if (domain != AF_INET)
355 {
356 sim_printf ("socket() domain EAFNOSUPPORT\n");
357 _errno = EAFNOSUPPORT;
358 }
359 # if defined(__APPLE__) || defined(_AIX) || defined(__HAIKU__)
360 else if (type != SOCK_STREAM && type != (SOCK_STREAM))
361 # else
362 else if (type != SOCK_STREAM && type != (SOCK_STREAM|SOCK_NONBLOCK))
363 # endif
364 {
365 sim_printf ("socket() type EPROTOTYPE\n");
366 _errno = EPROTOTYPE;
367 }
368 else if (protocol != 0)
369 {
370 sim_printf ("socket() protocol EPROTONOSUPPORT\n");
371 _errno = EPROTONOSUPPORT;
372 }
373 else
374 {
375 fd = socket ((int) buffer[0], (int) buffer[1], (int) buffer[2]);
376 sim_printf ("socket() returned %d\n", fd);
377 if (fd < 0)
378 {
379 sim_printf ("errno %d\n", errno);
380 _errno = errno;
381 }
382 else if (fd < N_FDS)
383 {
384 sk_data.fd_unit[fd] = (int) unit_idx;
385 sk_data.fd_dev_code[fd] = dev_code;
386 # if defined(__APPLE__) || defined(_AIX) || defined(__HAIKU__)
387 sk_data.fd_nonblock[fd] = 0;
388 # else
389 sk_data.fd_nonblock[fd] = !! (type & SOCK_NONBLOCK);
390 # endif
391 }
392 else
393 {
394 close (fd);
395 fd = -1;
396 _errno = EMFILE;
397 }
398 }
399
400 buffer[3] = ((word36) ((word36s) fd)) & MASK36;
401
402 set_error (& buffer[4], _errno);
403 }
404
405 static void skt_gethostbyname (word36 * buffer)
406 {
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421 word9 cnt = getbits36_9 (buffer [0], 27);
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 if (cnt > 256)
440 {
441 sim_warn ("socket$gethostbyname() clipping cnt from %u to 256\n", cnt);
442 cnt = 256;
443 }
444
445 unsigned char name [257];
446 for (uint i = 0; i < cnt; i ++)
447 {
448 uint wordno = (i+4) / 4;
449 uint offset = ((i+4) % 4) * 9;
450 word9 ch = getbits36_9 (buffer[wordno], offset);
451 name [i] = (unsigned char) (ch & 255);
452 }
453 name[cnt] = 0;
454
455 struct hostent * hostent = gethostbyname ((char *)name);
456 sim_printf ("gethostbyname returned %p\n", (void *) hostent);
457 if (hostent)
458 {
459 sim_printf ("addr_len %d\n", hostent->h_length);
460 sim_printf ("%hhu.%hhu.%hhu.%hhu\n", hostent->h_addr_list[0][0],hostent->h_addr_list[0][1], hostent->h_addr_list[0][2],hostent->h_addr_list[0][3]);
461
462 uint32_t addr = * ((uint32_t *) & hostent->h_addr_list[0][0]);
463 sim_printf ("addr %08x\n", addr);
464 addr = ntohl (addr);
465 sim_printf ("addr %08x\n", addr);
466 buffer[65] = ((word36) addr) << 4;
467
468
469
470
471
472 set_error (& buffer[66], 0);
473 }
474 else
475 {
476 sim_printf ("h_errno %d\n", h_errno);
477 switch (h_errno)
478 {
479 case HOST_NOT_FOUND: set_error_str (& buffer[66], "HOST_NOT_FOUND"); break;
480 case NO_DATA: set_error_str (& buffer[66], "NO_DATA"); break;
481 case NO_RECOVERY: set_error_str (& buffer[66], "NO_RECOVERY"); break;
482 case TRY_AGAIN: set_error_str (& buffer[66], "TRY_AGAIN"); break;
483 default: set_error_str (& buffer[66], "EHUH"); break;
484 }
485 }
486 }
487
488 static void skt_bind (uint unit_idx, word6 dev_code, word36 * buffer)
489 {
490
491
492
493
494
495
496
497
498
499
500
501
502
503 int socket_fd = (int) buffer[0];
504 int sin_family = (int) buffer[1];
505 unsigned short sin_port = (unsigned short) getbits36_16 (buffer [2], 0);
506 word8 octet [4] = { getbits36_8 (buffer [3], 0),
507 getbits36_8 (buffer [3], 8),
508 getbits36_8 (buffer [3], 16),
509 getbits36_8 (buffer [3], 24)};
510 uint32_t addr = (uint32_t) octet[0];
511 addr <<= 8;
512 addr |= (uint32_t) octet[1];
513 addr <<= 8;
514 addr |= (uint32_t) octet[2];
515 addr <<= 8;
516 addr |= (uint32_t) octet[3];
517
518 sim_printf ("bind() socket %d\n", socket_fd);
519 sim_printf ("bind() sin_family %d\n", sin_family);
520 sim_printf ("bind() sin_port %u\n", sin_port);
521 sim_printf ("bind() s_addr %hhu.%hhu.%hhu.%hhu\n", octet[0], octet[1], octet[2], octet[3]);
522 sim_printf ("bind() s_addr %08x\n", addr);
523
524
525
526
527
528
529 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
530 {
531 set_error (& buffer[4], EBADF);
532 return;
533 }
534
535 struct sockaddr_in serv_addr;
536 bzero ((char *) & serv_addr, sizeof(serv_addr));
537 serv_addr.sin_family = AF_INET;
538 serv_addr.sin_addr.s_addr = htonl (addr);
539 serv_addr.sin_port = htons (sin_port);
540
541 int _errno = 0;
542 int rc = bind (socket_fd, (struct sockaddr *) & serv_addr, sizeof (serv_addr));
543 sim_printf ("bind() returned %d\n", rc);
544
545 if (rc < 0)
546 {
547 sim_printf ("errno %d\n", errno);
548 _errno = errno;
549 }
550 set_error (& buffer[4], _errno);
551 }
552
553 static void skt_listen (uint unit_idx, word6 dev_code, word36 * buffer)
554 {
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569 int socket_fd = (int) buffer[0];
570 int backlog = (int) buffer[1];
571 sim_printf ("listen() socket %d\n", socket_fd);
572 sim_printf ("listen() backlog %d\n", backlog );
573
574 int rc = 0;
575 int _errno = 0;
576
577 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
578 {
579 sim_printf ("listen() socket doesn't belong to us\n");
580 sim_printf ("socket_fd %u fd_unit %d fd_dev_code %u unit_idx %u dev_code %u\n", socket_fd, sk_data.fd_unit[socket_fd], sk_data.fd_dev_code[socket_fd], unit_idx, dev_code);
581 _errno = EBADF;
582 goto done;
583 }
584
585 int on = 1;
586 rc = setsockopt (socket_fd, SOL_SOCKET, SO_REUSEADDR,
587 (char *) & on, sizeof (on));
588 sim_printf ("listen() setsockopt returned %d\n", rc);
589 if (rc < 0)
590 {
591 _errno = errno;
592 goto done;
593 }
594
595 # ifdef FIONBIO
596 rc = ioctl (socket_fd, FIONBIO, (char *) & on);
597 sim_printf ("listen() ioctl returned %d\n", rc);
598 if (rc < 0)
599 {
600 _errno = errno;
601 goto done;
602 }
603 # endif
604
605 rc = listen (socket_fd, backlog);
606 sim_printf ("listen() returned %d\n", rc);
607
608 if (rc < 0)
609 {
610 sim_printf ("errno %d\n", errno);
611 _errno = errno;
612 goto done;
613 }
614
615 done:
616 buffer[2] = ((word36) ((word36s) rc)) & MASK36;
617 set_error (& buffer[3], _errno);
618 }
619
620 static int skt_accept (uint unit_idx, word6 dev_code, word36 * buffer)
621 {
622
623
624
625
626
627
628
629
630
631
632 int socket_fd = (int) buffer[0];
633 sim_printf ("accept() socket %d\n", socket_fd);
634
635 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
636 {
637 set_error (& buffer[4], EBADF);
638 return IOM_CMD_DISCONNECT;
639 }
640
641 sk_data.unit_data[unit_idx][dev_code].accept_fd = socket_fd;
642 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_accept;
643 return IOM_CMD_DISCONNECT;
644 }
645
646 static void skt_close (uint unit_idx, word6 dev_code, word36 * buffer)
647 {
648
649
650
651
652
653
654
655
656
657
658
659
660 int socket_fd = (int) buffer[0];
661 sim_printf ("close() socket %d\n", socket_fd);
662
663 int rc = 0;
664 int _errno = 0;
665
666 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
667 {
668 sim_printf ("close() socket doesn't belong to us\n");
669 _errno = EBADF;
670 goto done;
671 }
672 sk_data.fd_unit[socket_fd] = -1;
673
674 if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_accept &&
675 sk_data.unit_data[unit_idx][dev_code].accept_fd == socket_fd)
676 {
677 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
678 sk_data.unit_data[unit_idx][dev_code].accept_fd = -1;
679 }
680 rc = close (socket_fd);
681
682 sim_printf ("close() close returned %d\n", rc);
683 if (rc < 0)
684 {
685 _errno = errno;
686 goto done;
687 }
688
689 done:
690 buffer[1] = ((word36) ((word36s) rc)) & MASK36;
691 set_error (& buffer[2], _errno);
692 }
693
694 static int skt_read8 (uint unit_idx, word6 dev_code, UNUSED uint tally, word36 * buffer)
695 {
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711 int socket_fd = (int) buffer[0];
712 uint count = (uint) buffer[1];
713 sim_printf ("read8() socket %d\n", socket_fd);
714
715
716 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
717 {
718 sim_printf ("read8() socket doesn't belong to us\n");
719 set_error (& buffer[4], EBADF);
720 return IOM_CMD_DISCONNECT;
721 }
722 sk_data.unit_data[unit_idx][dev_code].read_fd = socket_fd;
723 sk_data.unit_data[unit_idx][dev_code].read_buffer_sz = count;
724 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_read;
725 return IOM_CMD_DISCONNECT;
726 }
727
728 static int skt_write8 (uint iom_unit_idx, uint chan, uint unit_idx, word6 dev_code, uint tally, word36 * buffer)
729 {
730 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
731
732
733
734
735
736
737
738 if (tally < 5)
739 {
740 p->stati = 050012;
741 return IOM_CMD_ERROR;
742 }
743
744
745
746
747
748
749
750
751
752
753 int socket_fd = (int) buffer[0];
754 sim_printf ("write8() socket %d\n", socket_fd);
755
756 ssize_t rc = 0;
757 int _errno = 0;
758
759 if (sk_data.fd_unit[socket_fd] != (int) unit_idx || sk_data.fd_dev_code[socket_fd] != dev_code)
760 {
761 sim_printf ("write8() socket doesn't belong to us\n");
762 set_error (& buffer[3], EBADF);
763 return IOM_CMD_DISCONNECT;
764 }
765
766
767
768 word36 count36 = buffer[1];
769 if (count36 > (4091 * 4))
770 {
771 p->stati = 050012;
772 return IOM_CMD_ERROR;
773 }
774 uint count = (uint) count36;
775
776 uint count_words = (count + 3) / 4;
777 if ((count_words + 5) > tally)
778 {
779 p->stati = 050012;
780 return IOM_CMD_ERROR;
781 }
782
783 uint8_t netdata [count];
784 for (uint n = 0; n < count; n ++)
785 {
786 uint wordno = (uint) n / 4;
787 uint charno = (uint) n % 4;
788 netdata[n] = getbits36_8 (buffer [5 + wordno], charno * 9 + 1);
789
790 }
791
792 rc = write (socket_fd, netdata, count);
793 if (rc == -1)
794 _errno = errno;
795
796 buffer[2] = ((word36) ((word36s) rc)) & MASK36;
797 set_error (& buffer[3], _errno);
798 return IOM_CMD_DISCONNECT;
799 }
800
801 static int get_ddcw (iom_chan_data_t * p, uint iom_unit_idx, uint chan, bool * ptro, uint expected_tally, uint * tally)
802 {
803 bool send, uff;
804 int rc = iom_list_service (iom_unit_idx, chan, ptro, & send, & uff);
805 if (rc < 0)
806 {
807 p->stati = 05001;
808 sim_warn ("%s list service failed\n", __func__);
809 return IOM_CMD_ERROR;
810 }
811 if (uff)
812 {
813 sim_warn ("%s ignoring uff\n", __func__);
814 }
815 if (! send)
816 {
817 sim_warn ("%s nothing to send\n", __func__);
818 p->stati = 05001;
819 return IOM_CMD_ERROR;
820 }
821 if (IS_IDCW (p) || IS_TDCW (p))
822 {
823 sim_warn ("%s expected DDCW\n", __func__);
824 p->stati = 05001;
825 return IOM_CMD_ERROR;
826 }
827
828 * tally = p->DDCW_TALLY;
829 if (* tally == 0)
830 {
831 sim_debug (DBG_DEBUG, & skc_dev,
832 "%s: Tally of zero interpreted as 010000(4096)\n",
833 __func__);
834 * tally = 4096;
835 }
836
837 sim_debug (DBG_DEBUG, & skc_dev,
838 "%s: Tally %d (%o)\n", __func__, * tally, * tally);
839
840 if (expected_tally && * tally && * tally != expected_tally)
841 {
842 sim_warn ("socket_dev socket call expected tally of %d; got %d\n", expected_tally, * tally);
843 p->stati = 05001;
844 return IOM_CMD_ERROR;
845 }
846 return IOM_CMD_PROCEED;
847 }
848
849 static int sk_cmd (uint iom_unit_idx, uint chan)
850 {
851 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
852
853 sim_debug (DBG_DEBUG, & skc_dev, "IDCW_DEV_CODE %d\n", p->IDCW_DEV_CODE);
854 uint unit_idx = get_ctlr_idx (iom_unit_idx, chan);
855 sim_printf ("device %u\n", p->IDCW_DEV_CODE);
856 bool ptro;
857 switch (p->IDCW_DEV_CMD)
858 {
859 case 0:
860 {
861 p->stati = 04000;
862 sim_debug (DBG_DEBUG, & skc_dev,
863 "%s: Request status: %04o\n", __func__, p->stati);
864 sim_debug (DBG_DEBUG, & skc_dev,
865 "%s: Request status control: %o\n", __func__, p->IDCW_CHAN_CTRL);
866 sim_debug (DBG_DEBUG, & skc_dev,
867 "%s: Request status channel command: %o\n", __func__, p->IDCW_CHAN_CMD);
868 }
869 break;
870
871 case 01:
872 {
873 sim_debug (DBG_DEBUG, & skc_dev,
874 "%s: socket_dev_$socket\n", __func__);
875 const uint expected_tally = 6;
876 uint tally;
877 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
878 if (rc)
879 return rc;
880
881
882
883 word36 buffer [expected_tally];
884 uint words_processed;
885 iom_indirect_data_service (iom_unit_idx, chan, buffer,
886 & words_processed, false);
887
888 skt_socket (unit_idx, p->IDCW_DEV_CODE, buffer);
889
890 iom_indirect_data_service (iom_unit_idx, chan, buffer,
891 & words_processed, true);
892 }
893 break;
894
895 case 02:
896 {
897 sim_debug (DBG_DEBUG, & skc_dev,
898 "%s: socket_dev_$bind\n", __func__);
899
900 const uint expected_tally = 6;
901 uint tally;
902 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
903 if (rc)
904 return rc;
905
906
907
908 word36 buffer [expected_tally];
909 uint words_processed;
910 iom_indirect_data_service (iom_unit_idx, chan, buffer,
911 & words_processed, false);
912
913 skt_bind (unit_idx, p->IDCW_DEV_CODE, buffer);
914
915 iom_indirect_data_service (iom_unit_idx, chan, buffer,
916 & words_processed, true);
917
918 }
919 break;
920
921 case 03:
922 {
923 sim_printf ("socket_dev received command 3\r\n");
924 p->stati = 04000;
925 }
926 break;
927
928 case 04:
929 {
930 sim_debug (DBG_DEBUG, & skc_dev,
931 "%s: socket_dev_$gethostbyname\n", __func__);
932
933 const uint expected_tally = 68;
934 uint tally;
935 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
936 if (rc)
937 return rc;
938
939
940
941 word36 buffer [expected_tally];
942 uint words_processed;
943 iom_indirect_data_service (iom_unit_idx, chan, buffer,
944 & words_processed, false);
945
946 skt_gethostbyname (buffer);
947
948 iom_indirect_data_service (iom_unit_idx, chan, buffer,
949 & words_processed, true);
950
951 }
952 break;
953
954 case 05:
955 {
956 sim_debug (DBG_DEBUG, & skc_dev,
957 "%s: socket_dev_$listen\n", __func__);
958
959 const uint expected_tally = 5;
960 uint tally;
961 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
962 if (rc)
963 return rc;
964
965
966
967 word36 buffer [expected_tally];
968 uint words_processed;
969 iom_indirect_data_service (iom_unit_idx, chan, buffer,
970 & words_processed, false);
971
972 skt_listen (unit_idx, p->IDCW_DEV_CODE, buffer);
973
974 iom_indirect_data_service (iom_unit_idx, chan, buffer,
975 & words_processed, true);
976
977 }
978 break;
979
980 case 06:
981 {
982 sim_debug (DBG_DEBUG, & skc_dev,
983 "%s: socket_dev_$accept\n", __func__);
984
985 const uint expected_tally = 7;
986 uint tally;
987 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
988 if (rc)
989 return rc;
990
991
992
993 word36 buffer [expected_tally];
994 uint words_processed;
995 iom_indirect_data_service (iom_unit_idx, chan, buffer,
996 & words_processed, false);
997 sk_data.unit_data[unit_idx][p->IDCW_DEV_CODE].words_processed = words_processed;
998
999 rc = skt_accept (unit_idx, p->IDCW_DEV_CODE, buffer);
1000
1001 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1002 & words_processed, true);
1003
1004 return rc;
1005
1006 }
1007
1008 break;
1009
1010 case 07:
1011 {
1012 sim_debug (DBG_DEBUG, & skc_dev,
1013 "%s: socket_dev_$close\n", __func__);
1014
1015 const uint expected_tally = 4;
1016 uint tally;
1017 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1018 if (rc)
1019 return rc;
1020
1021
1022
1023 word36 buffer [expected_tally];
1024 uint words_processed;
1025 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1026 & words_processed, false);
1027
1028 skt_close (unit_idx, p->IDCW_DEV_CODE, buffer);
1029
1030 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1031 & words_processed, true);
1032 }
1033 break;
1034
1035 case 8:
1036 {
1037 sim_debug (DBG_DEBUG, & skc_dev,
1038 "%s: socket_dev_$read8\n", __func__);
1039
1040 const uint expected_tally = 0;
1041 uint tally;
1042 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1043 if (rc)
1044 return rc;
1045
1046
1047
1048 word36 buffer[4096];
1049 uint words_processed;
1050 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1051 & words_processed, false);
1052 sk_data.unit_data[unit_idx][p->IDCW_DEV_CODE].words_processed = words_processed;
1053
1054 rc = skt_read8 (unit_idx, p->IDCW_DEV_CODE, tally, buffer);
1055
1056 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1057 & words_processed, true);
1058 return rc;
1059
1060 }
1061
1062 break;
1063
1064 case 9:
1065 {
1066 sim_debug (DBG_DEBUG, & skc_dev,
1067 "%s: socket_dev_$write8\n", __func__);
1068
1069 const uint expected_tally = 0;
1070 uint tally;
1071 int rc = get_ddcw (p, iom_unit_idx, chan, & ptro, expected_tally, & tally);
1072 if (rc)
1073 return rc;
1074
1075
1076
1077 word36 buffer[4096];
1078 uint words_processed;
1079 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1080 & words_processed, false);
1081
1082 rc = skt_write8 (iom_unit_idx, chan, unit_idx, p->IDCW_DEV_CODE, tally, buffer);
1083
1084 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1085 & words_processed, true);
1086 return rc;
1087 }
1088
1089 break;
1090
1091 case 040:
1092 {
1093 p->stati = 04000;
1094 sim_debug (DBG_DEBUG, & skc_dev,
1095 "%s: Reset status is %04o.\n",
1096 __func__, p->stati);
1097 return IOM_CMD_PROCEED;
1098 }
1099
1100 default:
1101 {
1102 p->stati = 04501;
1103 p->chanStatus = chanStatIncorrectDCW;
1104 if (p->IDCW_DEV_CMD != 051)
1105 sim_warn ("%s: Unknown command 0%o\n", __func__, p->IDCW_DEV_CMD);
1106 }
1107 return IOM_CMD_ERROR;
1108
1109 }
1110
1111 sim_debug (DBG_DEBUG, & skc_dev, "stati %04o\n", p->stati);
1112
1113
1114
1115
1116
1117
1118
1119 return IOM_CMD_DISCONNECT;
1120 }
1121
1122 iom_cmd_rc_t skc_iom_cmd (uint iom_unit_idx, uint chan)
1123 {
1124 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx] [chan];
1125
1126
1127 int rc = 0;
1128 if (IS_IDCW (p))
1129 {
1130 rc = sk_cmd (iom_unit_idx, chan);
1131 }
1132 else
1133 {
1134 sim_warn ("%s expected IDCW\n", __func__);
1135 return IOM_CMD_ERROR;
1136 }
1137 return rc;
1138 }
1139
1140 static void do_try_accept (uint unit_idx, word6 dev_code)
1141 {
1142 struct sockaddr_in from = { .sin_family = AF_INET };
1143 socklen_t size = sizeof (from);
1144 int _errno = 0;
1145 int fd = accept (sk_data.unit_data[unit_idx][dev_code].accept_fd, (struct sockaddr *) & from, & size);
1146 if (fd == -1)
1147 {
1148 if (errno == EAGAIN || errno == EWOULDBLOCK)
1149 return;
1150 _errno = errno;
1151 }
1152 else if (fd < N_FDS)
1153 {
1154 sk_data.fd_unit[fd] = (int) unit_idx;
1155 sk_data.fd_dev_code[fd] = dev_code;
1156 sk_data.fd_nonblock[fd] = false ;
1157 }
1158 else
1159 {
1160 close (fd);
1161 fd = -1;
1162 _errno = EMFILE;
1163 }
1164 word36 buffer [7];
1165
1166 buffer[0] = ((word36) ((word36s) sk_data.unit_data[unit_idx][dev_code].accept_fd)) & MASK36;
1167 buffer[1] = ((word36) ((word36s) fd)) & MASK36;
1168 buffer[2] = ((word36) ((word36s) from.sin_family)) & MASK36;
1169 uint16_t port = ntohs (from.sin_port);
1170 putbits36_16 (& buffer[3], 0, port);
1171 uint32_t addr = ntohl (from.sin_addr.s_addr);
1172 buffer[4] = ((word36) addr) << 4;
1173 set_error (& buffer[5], _errno);
1174
1175
1176 uint iom_unit_idx = (uint) cables->sk_to_iom[unit_idx][0].iom_unit_idx;
1177 uint chan = (uint) cables->sk_to_iom[unit_idx][0].chan_num;
1178 uint words_processed = sk_data.unit_data[unit_idx][dev_code].words_processed;
1179 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1180 & words_processed, true);
1181 iom_chan_data_t * p = & iom_chan_data[iom_unit_idx][chan];
1182 p->stati = 04000;
1183 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
1184 send_terminate_interrupt (iom_unit_idx, chan);
1185 }
1186
1187 static void do_try_read (uint unit_idx, word6 dev_code)
1188 {
1189 int _errno = 0;
1190 uint count = sk_data.unit_data[unit_idx][dev_code].read_buffer_sz;
1191 uint buffer_size_wds = (count + 3) / 4;
1192 word36 buffer [buffer_size_wds];
1193
1194 memset (buffer, 0, sizeof (word36) * buffer_size_wds);
1195 uint8_t netdata [count];
1196 ssize_t nread = read (sk_data.unit_data[unit_idx][dev_code].read_fd, & netdata, count);
1197 if (nread == -1)
1198 {
1199 if (errno == EAGAIN || errno == EWOULDBLOCK)
1200 return;
1201 _errno = errno;
1202 nread = 0;
1203 }
1204
1205
1206 buffer[0] = ((word36) ((word36s) sk_data.unit_data[unit_idx][dev_code].read_fd)) & MASK36;
1207 buffer[1] = ((word36) (sk_data.unit_data[unit_idx][dev_code].read_buffer_sz)) & MASK36;
1208 buffer[2] = ((word36) ((word36s) nread)) & MASK36;
1209 set_error (& buffer[3], _errno);
1210
1211 for (ssize_t n = 0; n < nread; n ++)
1212 {
1213 uint wordno = (uint) n / 4;
1214 uint charno = (uint) n % 4;
1215 putbits36_9 (& buffer [5 + wordno], charno * 9, (word9) netdata [n]);
1216 }
1217
1218
1219
1220 uint iom_unit_idx = (uint) cables->sk_to_iom[unit_idx][0].iom_unit_idx;
1221 uint chan = (uint) cables->sk_to_iom[unit_idx][0].chan_num;
1222 uint words_processed = sk_data.unit_data[unit_idx][dev_code].words_processed;
1223 iom_indirect_data_service (iom_unit_idx, chan, buffer,
1224 & words_processed, true);
1225 sk_data.unit_data[unit_idx][dev_code].unit_state = unit_idle;
1226 send_terminate_interrupt (iom_unit_idx, chan);
1227 }
1228
1229 void sk_process_event (void)
1230 {
1231
1232 for (uint unit_idx = 0; unit_idx < N_SKC_UNITS_MAX; unit_idx ++)
1233 {
1234 for (word6 dev_code = 0; dev_code < N_DEV_CODES; dev_code ++)
1235 {
1236 if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_accept)
1237 {
1238 do_try_accept (unit_idx, dev_code);
1239 }
1240 else if (sk_data.unit_data[unit_idx][dev_code].unit_state == unit_read)
1241 {
1242 do_try_read (unit_idx, dev_code);
1243 }
1244 }
1245 }
1246 }
1247 #endif