This source file includes following definitions.
- fnpuv_complete_selection
- register_client
- unregister_client
- tun_alloc
- alloc_buffer
- fnpuv_cap_send_buffer
- fnpuv_output_backlogged
- fnpuv_associated_brk
- fnpuv_associated_readcb
- fnpuv_3270_readcb
- fnpuv_unassociated_readcb
- fuv_close_cb
- close_unassociated_socket
- fuv_listener_close_cb
- close_listener
- fnpuv_peer_name
- close_connection
- fuv_read_cb
- fuv_write_cb
- fuv_write_3270_cb
- fnpuv_start_write_3270_actual
- fnpuv_start_write_actual
- fnpuv_start_write
- fnpuv_start_3270_write
- fnpuv_start_writestr
- fnpuv_send_eor
- fnpuv_recv_eor
- fnpuv_read_start
- fnpuv_read_stop
- on_new_connection
- fnpuvInit
- fnpuvProcessEvent
- fnpuvExit
- on_dialout_connect
- fnpuv_dial_out
- fnpuv_open_slave
- processPacketInput
- fnoTUNProcessLine
- fnpTUNProcessEvent
- fnpuv3270Poll
- on_new_3270_connection
- fnpuv3270Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 #if defined(TUN)
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 #endif
179
180 #define ASSUME0 0
181
182 #include <stdio.h>
183 #include <stdlib.h>
184 #include <string.h>
185 #include <limits.h>
186 #include <unistd.h>
187 #include <ctype.h>
188 #include <signal.h>
189 #if defined(TUN)
190 # include <string.h>
191 # include <fcntl.h>
192 # include <errno.h>
193 # include <sys/ioctl.h>
194 # include <sys/types.h>
195 # include <sys/stat.h>
196 # include <netinet/in.h>
197 # include <sys/socket.h>
198 # include <linux/if.h>
199 # include <linux/if_tun.h>
200 #endif
201
202 #include "dps8.h"
203 #include "dps8_sys.h"
204 #include "dps8_iom.h"
205 #include "dps8_cable.h"
206 #include "dps8_cpu.h"
207 #include "dps8_scu.h"
208 #include "dps8_fnp2.h"
209 #include "dps8_utils.h"
210 #include "fnpuv.h"
211 #include "uvutil.h"
212 #include "fnptelnet.h"
213
214 #if defined(NO_LOCALE)
215 # define xstrerror_l strerror
216 #endif
217
218 #if defined(FREE)
219 # undef FREE
220 #endif
221 #define FREE(p) do \
222 { \
223 free((p)); \
224 (p) = NULL; \
225 } while(0)
226
227 #define USE_REQ_DATA
228
229
230 #define DEFAULT_BACKLOG 1024
231
232
233
234
235
236 #define FNP_MAX_SELECTING 256U
237 #define FNP_MAX_SELECTING_IP 16U
238 #define FNP_SELECT_TIMEOUT_NS UINT64_C(120000000000)
239
240
241
242
243
244
245
246
247 #define FNP_MAX_SNDBUF 16384
248 #define FNP_MAX_WRITE_QUEUE 8192U
249
250 static uvClientData * fnp_clients;
251 static unsigned int fnp_pending_closes;
252 static unsigned int fnp_selecting;
253
254 void fnpuv_complete_selection (uvClientData * p)
255 {
256 if (p->selection_pending)
257 {
258 p->selection_pending = false;
259 p->selection_deadline_ns = 0;
260 if (fnp_selecting)
261 fnp_selecting --;
262 }
263 }
264
265 static void register_client (uv_tcp_t * client, uvClientData * p)
266 {
267 p->client = client;
268 p->next = fnp_clients;
269 if (fnp_clients)
270 fnp_clients->prev = p;
271 fnp_clients = p;
272 client->data = p;
273 }
274
275 static void unregister_client (uvClientData * p)
276 {
277 fnpuv_complete_selection (p);
278 if (p->prev)
279 p->prev->next = p->next;
280 else
281 fnp_clients = p->next;
282 if (p->next)
283 p->next->prev = p->prev;
284 }
285
286 #if defined(TUN)
287 static int tun_alloc (char * dev)
288 {
289 struct ifreq ifr;
290 int fd, err;
291
292 if ((fd = open ("/dev/net/tun", O_RDWR)) < 0)
293
294 return fd;
295
296 (void)memset (& ifr, 0, sizeof (ifr));
297
298
299
300
301
302
303
304
305 ifr.ifr_flags = IFF_TUN;
306 if (* dev)
307 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
308
309 if ((err = ioctl (fd, TUNSETIFF, (void *) & ifr)) < 0)
310 {
311 close (fd);
312 return err;
313 }
314 strcpy (dev, ifr.ifr_name);
315 return fd;
316 }
317 #endif
318
319
320
321
322
323 static void alloc_buffer (UNUSED uv_handle_t * handle, size_t suggested_size,
324 uv_buf_t * buf)
325 {
326
327 #if !defined(__clang_analyzer__)
328 if (suggested_size > UINT_MAX)
329 suggested_size = UINT_MAX;
330 char * base = (char *)malloc (suggested_size);
331 *buf = uv_buf_init (base, base ? (unsigned int)suggested_size : 0);
332 #endif
333 }
334
335
336
337
338
339
340 static void fnpuv_cap_send_buffer (uv_tcp_t * client)
341 {
342 int size = FNP_MAX_SNDBUF;
343 int rc = uv_send_buffer_size ((uv_handle_t *) client, & size);
344 if (rc < 0)
345 sir_error ("FNP: uv_send_buffer_size failed: %s",
346 uv_strerror (rc));
347 }
348
349
350
351
352 bool fnpuv_output_backlogged (uv_tcp_t * client)
353 {
354 if (! client || uv_is_closing ((uv_handle_t *) client))
355 return false;
356 return uv_stream_get_write_queue_size ((uv_stream_t *) client) >
357 FNP_MAX_WRITE_QUEUE;
358 }
359
360 void fnpuv_associated_brk (uv_tcp_t * client)
361 {
362 if (! client || uv_is_closing ((uv_handle_t *) client))
363 return;
364 if (! client->data)
365 {
366 sim_warn ("fnpuv_associated_brk bad client data\r\n");
367 return;
368 }
369 uvClientData * p = (uvClientData *) client->data;
370 if (!p->assoc || p->fnpno >= N_FNP_UNITS_MAX || p->lineno >= MAX_LINES)
371 return;
372 uint fnpno = p -> fnpno;
373 uint lineno = p -> lineno;
374 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
375
376
377
378 linep->accept_input = 1;
379 linep->line_break=true;
380 }
381
382
383
384
385 void fnpuv_associated_readcb (uv_tcp_t * client,
386 ssize_t nread,
387 unsigned char * buf)
388 {
389 processLineInput (client, buf, nread);
390 }
391
392 void fnpuv_3270_readcb (uv_tcp_t * client,
393 ssize_t nread,
394 unsigned char * buf)
395 {
396 process3270Input (client, buf, nread);
397 }
398
399
400
401
402 void fnpuv_unassociated_readcb (uv_tcp_t * client,
403 ssize_t nread,
404 unsigned char * buf)
405 {
406
407 processUserInput (client, buf, nread);
408 }
409
410 static void fuv_close_cb (uv_handle_t * stream)
411 {
412
413
414 uvClientData * p = (uvClientData *)stream->data;
415 if (p)
416 {
417 unregister_client (p);
418 if (p->telnetp)
419 telnet_free (p->telnetp);
420 FREE (p->ttype);
421 FREE (p);
422 }
423 FREE (stream);
424 fnp_pending_closes --;
425 }
426
427 static void close_unassociated_socket (uv_tcp_t * client)
428 {
429 if (!uv_is_closing ((uv_handle_t *)client))
430 {
431 fnp_pending_closes ++;
432 uv_close ((uv_handle_t *)client, fuv_close_cb);
433 }
434 }
435
436 static void fuv_listener_close_cb (uv_handle_t * handle)
437 {
438 uvClientData * p = (uvClientData *)handle->data;
439 FREE (p);
440 handle->data = NULL;
441 if (handle == (uv_handle_t *)&fnpData.du_server)
442 fnpData.du_server_inited = false;
443 if (handle == (uv_handle_t *)&fnpData.du3270_server)
444 fnpData.du3270_server_inited = false;
445 fnp_pending_closes --;
446 }
447
448 static void close_listener (uv_tcp_t * server)
449 {
450 if (!uv_is_closing ((uv_handle_t *)server))
451 {
452 fnp_pending_closes ++;
453 uv_close ((uv_handle_t *)server, fuv_listener_close_cb);
454 }
455 }
456
457
458
459
460 const char * fnpuv_peer_name (uv_tcp_t * client, char * text, size_t len)
461 {
462 struct sockaddr_storage addr;
463 int addrlen = sizeof (addr);
464 if (!client || !text || !len ||
465 uv_tcp_getpeername (client, (struct sockaddr *)&addr, &addrlen) < 0)
466 return NULL;
467 if (addr.ss_family == AF_INET)
468 {
469 struct sockaddr_in ipv4;
470
471
472 if (addrlen < 0 || (size_t)addrlen < sizeof (ipv4))
473 return NULL;
474 memcpy (&ipv4, &addr, sizeof (ipv4));
475 return uv_ip4_name (&ipv4, text, len) == 0 ? text : NULL;
476 }
477 if (addr.ss_family == AF_INET6)
478 {
479 struct sockaddr_in6 ipv6;
480 if (addrlen < 0 || (size_t)addrlen < sizeof (ipv6))
481 return NULL;
482 memcpy (&ipv6, &addr, sizeof (ipv6));
483 return uv_ip6_name (&ipv6, text, len) == 0 ? text : NULL;
484 }
485 return NULL;
486 }
487
488
489
490 void close_connection (uv_stream_t* stream)
491 {
492 if (! stream || uv_is_closing ((uv_handle_t *)stream))
493 {
494 sim_warn ("close_connection bad client data\r\n");
495 return;
496 }
497 uvClientData * p = (uvClientData *) stream->data;
498
499 char ip[128];
500 const char *rname = fnpuv_peer_name ((uv_tcp_t *)stream, ip, sizeof (ip));
501
502
503
504
505 if (p)
506 {
507
508
509 if (p->assoc)
510 {
511 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
512 if (linep->service == service_3270)
513 {
514
515 if (rname == NULL)
516 sim_printf ("\r[FNP emulation: TN3270 %d.%d DISCONNECT]\r\n", ASSUME0, p->stationNo);
517 else
518 sim_printf ("\r[FNP emulation: TN3270 %d.%d DISCONNECT %s]\r\n", ASSUME0, p->stationNo, rname);
519 }
520 else
521 {
522 if (rname == NULL)
523 sim_printf ("\r[FNP emulation: DISCONNECT %c.d%03d]\r\n", p->fnpno+'a', p->lineno);
524 else
525 sim_printf ("\r[FNP emulation: DISCONNECT %c.d%03d %s]\r\n", p->fnpno+'a', p->lineno, rname);
526 #if defined(DISC_DELAY)
527 linep -> line_disconnected = DISC_DELAY;
528 #else
529 linep -> line_disconnected = true;
530 #endif
531 linep -> listen = false;
532 if (linep->inBuffer)
533 FREE (linep->inBuffer);
534 linep->inBuffer = NULL;
535 linep->inSize = 0;
536 linep->inUsed = 0;
537 linep->nPos = 0;
538
539
540
541 linep->input_cancelled = linep->input_reply_pending ||
542 linep->input_in_mailbox_pending;
543 linep->input_retry_at_ns = 0;
544 linep->accept_input = 0;
545 linep->input_break = false;
546 linep->force_accept_input = false;
547 linep->send_output = 0;
548 }
549 if (linep->line_client == (uv_tcp_t *)stream)
550 {
551 linep->line_client = NULL;
552 }
553 }
554 else
555 {
556 libtelnet_set_invalid(p->telnetp);
557 if (rname == NULL)
558 sim_printf ("\r[FNP emulation: DISCONNECT]\r\n");
559 else
560 sim_printf ("\r[FNP emulation: DISCONNECT %s]\r\n", rname);
561 }
562 if (p->stationNo < IBM3270_STATIONS_MAX &&
563 fnpData.ibm3270ctlr[ASSUME0].stations[p->stationNo].client == (uv_tcp_t *)stream)
564 {
565 struct station_s * stnp =
566 &fnpData.ibm3270ctlr[ASSUME0].stations[p->stationNo];
567 stnp->client = NULL;
568 FREE (stnp->stn_in_buffer);
569 stnp->stn_in_size = stnp->stn_in_used = 0;
570 stnp->EORReceived = false;
571 stnp->hdr_sent = false;
572 if (fnpData.ibm3270ctlr[ASSUME0].stn_no == p->stationNo)
573 fnpData.ibm3270ctlr[ASSUME0].sending_stn_in_buffer = false;
574 }
575
576
577 libtelnet_set_invalid (p->telnetp);
578 }
579 (void)uv_read_stop (stream);
580 close_unassociated_socket ((uv_tcp_t *)stream);
581 }
582
583
584
585
586
587
588
589 static void fuv_read_cb (uv_stream_t* stream,
590 ssize_t nread,
591 const uv_buf_t* buf)
592 {
593 if (nread < 0)
594 {
595
596 {
597 close_connection (stream);
598 }
599 }
600 else if (nread > 0)
601 {
602 if (! stream || uv_is_closing ((uv_handle_t *)stream))
603 {
604 sim_warn ("fuv_read_cb bad client data\r\n");
605 goto done;
606 }
607 uvClientData * p = (uvClientData *) stream->data;
608 if (p && buf && buf->base)
609 {
610 if (p->telnetp && libtelnet_is_valid (p->telnetp))
611 {
612 telnet_recv (p->telnetp, buf->base, (size_t) nread);
613 }
614 else
615 {
616
617 if (!p->telnetp && p->read_cb)
618 (* p->read_cb) ((uv_tcp_t *) stream, nread, (unsigned char *) buf->base);
619
620
621
622
623
624
625
626
627
628
629
630 }
631 }
632 }
633
634 done:
635 if (buf && buf->base)
636 free (buf->base);
637 }
638
639
640
641
642
643
644
645
646 static void fuv_write_cb (uv_write_t * req, int status)
647 {
648 if (status < 0)
649 {
650 if (status == -ECONNRESET || status == -ECANCELED ||
651 status == -EPIPE)
652 {
653
654 }
655 else
656 {
657 sim_warn ("fuv_write_cb status %d (%s)\r\n", -status, xstrerror_l(-status));
658 }
659
660
661 if (!uv_is_closing ((uv_handle_t *)req->handle))
662 close_connection (req->handle);
663 }
664
665 #if defined(USE_REQ_DATA)
666
667 FREE (req->data);
668 #else
669 unsigned int nbufs = req->nbufs;
670 uv_buf_t * bufs = req->bufs;
671 for (unsigned int i = 0; i < nbufs; i ++)
672 {
673 if (bufs && bufs[i].base)
674 {
675
676 FREE (bufs[i].base);
677 }
678 if (req->bufsml[i].base)
679 {
680
681 FREE (req->bufsml[i].base);
682 }
683 }
684 #endif
685
686
687
688 FREE (req);
689 }
690
691
692
693
694
695
696
697
698 static void fuv_write_3270_cb (uv_write_t * req, int status) {
699 uv_tcp_t * client = (uv_tcp_t *) req->handle;
700 fuv_write_cb (req, status);
701 set_3270_write_complete (client);
702 }
703
704
705
706 static void fnpuv_start_write_3270_actual (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
707 {
708 if (!client || uv_is_closing ((uv_handle_t *)client) || !data ||
709 datalen <= 0 || (uint64_t)datalen > UINT_MAX)
710 return;
711 #if defined(TESTING)
712 sim_printf ("fnpuv_start_write_3270_actual\r\n");
713 #endif
714
715
716
717 uint stn_no;
718 for (stn_no = 0; stn_no < ADDR_MAP_ENTRIES; stn_no ++)
719 if (addr_map [stn_no] == fnpData.ibm3270ctlr[ASSUME0].selDevChar)
720 break;
721 if (stn_no >= ADDR_MAP_ENTRIES)
722 {
723 sim_printf ("fnpuv_start_write_3270_actual couldn't find selDevChar %02x\r\n",
724 (unsigned int) fnpData.ibm3270ctlr[ASSUME0].selDevChar);
725 return;
726 }
727 uv_tcp_t * stn_client = fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client;
728 if (! stn_client || uv_is_closing ((uv_handle_t *) stn_client))
729 return;
730
731
732
733 #if !defined (__clang_analyzer__)
734 uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
735 if (!req)
736 {
737 sim_warn ("TN3270 write allocation failed; dropping output\r\n");
738 return;
739 }
740
741 (void)memset (req, 0, sizeof (uv_write_t));
742 uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
743 if (!buf.base)
744 {
745 FREE (req);
746 return;
747 }
748
749 # if defined(USE_REQ_DATA)
750 req->data = buf.base;
751 # endif
752
753 memcpy (buf.base, data, (unsigned long) datalen);
754 int ret = uv_write (req, (uv_stream_t *) stn_client, & buf, 1, fuv_write_3270_cb);
755
756
757
758
759 if (ret < 0)
760 {
761 if (ret != UV_EBADF)
762 sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
763 FREE (buf.base);
764 FREE (req);
765 }
766 #endif
767 }
768
769 void fnpuv_start_write_actual (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
770 {
771 if (!client || uv_is_closing ((uv_handle_t *)client) || !data ||
772 datalen <= 0 || (uint64_t)datalen > UINT_MAX)
773 return;
774
775 #if !defined(__clang_analyzer__)
776 uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
777 if (!req)
778 {
779 sim_warn ("FNP write allocation failed; dropping output\r\n");
780 return;
781 }
782
783 (void)memset (req, 0, sizeof (uv_write_t));
784 uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
785 if (!buf.base)
786 {
787 FREE (req);
788 return;
789 }
790
791 # if defined(USE_REQ_DATA)
792 req->data = buf.base;
793 # endif
794
795 memcpy (buf.base, data, (unsigned long) datalen);
796 int ret = uv_write (req, (uv_stream_t *) client, & buf, 1, fuv_write_cb);
797
798
799
800
801 if (ret < 0)
802 {
803 if (ret != UV_EBADF)
804 sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
805 FREE (buf.base);
806 FREE (req);
807 }
808 #endif
809 }
810
811
812
813
814
815 void fnpuv_start_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
816 {
817 if (! client || uv_is_closing ((uv_handle_t *) client) ||
818 !data || datalen <= 0)
819 return;
820 uvClientData * p = (uvClientData *) client->data;
821 if (! p)
822 return;
823 if (!p->telnetp)
824 {
825 sim_warn ("telnetp NULL; dropping fnpuv_start_write()\r\n");
826 return;
827 }
828 telnet_send (p->telnetp, (char *) data, (size_t) datalen);
829 }
830
831 void fnpuv_start_3270_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
832 {
833 if (! client || uv_is_closing ((uv_handle_t *) client) || ! client->data ||
834 !data || datalen <= 0)
835 return;
836 uvClientData * p = (uvClientData *) client->data;
837 if (! p)
838 return;
839 #if defined(TESTING)
840 sim_printf ("fnpuv_start_3270_write\r\n");
841 #endif
842
843
844
845
846
847 if (datalen == 1 && data [0] == 0x37)
848 {
849 #if defined(TESTING)
850 sim_printf ("fnpuv: detected EOT\r\n");
851 #endif
852 fnpuv_send_eor (client);
853 return;
854 }
855
856 unsigned char * actual_data_start = data;
857 unsigned long actual_datalen = (unsigned long) datalen;
858
859 if (data [datalen - 1] == 0x03)
860 {
861 actual_datalen --;
862
863 }
864 if (data [0] == 0x02)
865 {
866 actual_data_start ++;
867 actual_datalen --;
868 if (actual_datalen > 0 && data [1] == 0x27)
869 {
870 actual_data_start ++;
871 actual_datalen --;
872 }
873 }
874
875
876
877 if (actual_datalen > 0)
878 {
879 telnet_send (p->telnetp, (char *) actual_data_start, (size_t) actual_datalen);
880 }
881 }
882
883
884
885 void fnpuv_start_writestr (uv_tcp_t * client, unsigned char * data)
886 {
887
888 if (! client || uv_is_closing ((uv_handle_t *) client))
889 return;
890 if (! client->data)
891 {
892 sim_warn ("fnpuv_start_writestr bad client data\r\n");
893 return;
894 }
895 uvClientData * p = client->data;
896 if (p->write_cb && data)
897 (* p->write_cb) (client, data, (ssize_t) strlen ((char *) data));
898 }
899
900 void fnpuv_send_eor (uv_tcp_t * client)
901 {
902 if (! client || uv_is_closing ((uv_handle_t *) client))
903 return;
904 if (! client->data)
905 {
906 sim_warn ("fnpuv_send_eor bad client data\r\n");
907 return;
908 }
909 uvClientData * p = (uvClientData *) client->data;
910 ltnEOR (p->telnetp);
911
912
913 }
914
915 void fnpuv_recv_eor (uv_tcp_t * client)
916 {
917 fnpRecvEOR (client);
918 }
919
920
921
922
923
924 void fnpuv_read_start (uv_tcp_t * client)
925 {
926 if (! client || uv_is_closing ((uv_handle_t *) client))
927 return;
928 uv_read_start ((uv_stream_t *) client, alloc_buffer, fuv_read_cb);
929 }
930
931
932
933
934
935 void fnpuv_read_stop (uv_tcp_t * client)
936 {
937 if (! client || uv_is_closing ((uv_handle_t *) client))
938 return;
939 uv_read_stop ((uv_stream_t *) client);
940 }
941
942
943
944
945
946 static void on_new_connection (uv_stream_t * server, int status)
947 {
948 if (status < 0)
949 {
950 sim_printf ("\r[FNP emulation: new connection error: %s]\r\n", uv_strerror(status));
951
952 return;
953 }
954
955 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
956 if (!client)
957 {
958 sim_warn ("FNP dialin allocation failed; rejecting connection\r\n");
959 return;
960 }
961 int init_rc = uv_tcp_init (fnpData.loop, client);
962 if (init_rc < 0)
963 {
964 sim_warn ("dialin TCP initialization failed: %s\r\n", uv_strerror (init_rc));
965 FREE (client);
966 return;
967 }
968 client->data = NULL;
969 if (uv_accept (server, (uv_stream_t *) client) != 0)
970 {
971 close_unassociated_socket (client);
972 return;
973 }
974 fnpuv_cap_send_buffer (client);
975
976
977
978
979 char selecting_peer[128] = "unknown";
980 if (!server->data)
981 {
982 (void)fnpuv_peer_name (client, selecting_peer, sizeof (selecting_peer));
983 unsigned int same_ip = 0;
984 for (uvClientData * q = fnp_clients; q; q = q->next)
985 if (q->selection_pending &&
986 strcmp (q->selection_peer, selecting_peer) == 0)
987 same_ip ++;
988 if (fnp_selecting >= FNP_MAX_SELECTING || same_ip >= FNP_MAX_SELECTING_IP)
989 {
990 close_unassociated_socket (client);
991 return;
992 }
993 }
994
995
996
997 if (server->data)
998 {
999 uvClientData * p = (uvClientData *) server->data;
1000 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
1001
1002
1003 if (linep->line_client)
1004 {
1005 close_unassociated_socket (client);
1006 # if defined(TESTING)
1007 sim_printf ("\r[FNP emulation: dropping 2nd slave]\r\n");
1008 # endif
1009 return;
1010 }
1011
1012 linep->line_client = client;
1013 }
1014
1015 uv_tcp_nodelay (client,1);
1016 char peer[128];
1017 const char *name = fnpuv_peer_name (client, peer, sizeof (peer));
1018 if (!name)
1019 {
1020 sim_printf ("\r[FNP emulation: CONNECT; address unavailable]\r\n");
1021 }
1022 else
1023 {
1024 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", name);
1025 }
1026
1027 uvClientData * p = (uvClientData *) calloc (1, sizeof (uvClientData));
1028 if (! p)
1029 {
1030 sim_warn ("FNP dialin session allocation failed; closing client\r\n");
1031 if (server->data)
1032 {
1033 uvClientData * q = (uvClientData *)server->data;
1034 struct t_line * linep = &fnpData.fnpUnitData[q->fnpno].MState.line[q->lineno];
1035 if (linep->line_client == client)
1036 linep->line_client = NULL;
1037 }
1038 close_unassociated_socket (client);
1039 return;
1040 }
1041 register_client (client, p);
1042 if (!server->data)
1043 {
1044 p->selection_pending = true;
1045 p->selection_deadline_ns = uv_hrtime () + FNP_SELECT_TIMEOUT_NS;
1046 (void)strncpy (p->selection_peer, selecting_peer,
1047 sizeof (p->selection_peer) - 1);
1048 fnp_selecting ++;
1049 }
1050 p->assoc = false;
1051 p->nPos = 0;
1052 p->ttype = NULL;
1053 p->write_actual_cb = fnpuv_start_write_actual;
1054
1055 if (! server->data)
1056 {
1057 p->read_cb = fnpuv_unassociated_readcb;
1058 p->write_cb = fnpuv_start_write;
1059 p->telnetp = ltnConnect (client);
1060
1061 if (! p->telnetp)
1062 {
1063 sim_warn ("ltnConnect failed\r\n");
1064 close_connection ((uv_stream_t *)client);
1065 return;
1066 }
1067 }
1068 else
1069 {
1070 p->read_cb = fnpuv_associated_readcb;
1071 p->write_cb = fnpuv_start_write_actual;
1072 p->telnetp = NULL;
1073 uvClientData * q = (uvClientData *) server->data;
1074 p->fnpno = q->fnpno;
1075 p->lineno = q->lineno;
1076 p->assoc = true;
1077 }
1078 fnpuv_read_start (client);
1079 if (! server->data)
1080 fnpConnectPrompt (client);
1081 else
1082 {
1083 uvClientData * p = (uvClientData *) server->data;
1084 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
1085 if (linep->lineType == 0)
1086 linep->lineType = 1;
1087 linep->accept_new_terminal = true;
1088 reset_line (linep);
1089 }
1090 }
1091
1092
1093
1094
1095
1096 int fnpuvInit (int telnet_port, char * telnet_address)
1097 {
1098 const char * bind_address = telnet_address ? telnet_address : "0.0.0.0";
1099
1100
1101
1102 if (fnpData.du_server_inited)
1103 {
1104 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
1105 return 1;
1106 }
1107
1108 if (! fnpData.loop)
1109 fnpData.loop = uv_default_loop ();
1110
1111
1112
1113 int r = uv_tcp_init (fnpData.loop, & fnpData.du_server);
1114 if (r < 0)
1115 return 1;
1116 fnpData.du_server_inited = true;
1117
1118
1119
1120
1121
1122 fnpData.du_server.data = NULL;
1123
1124
1125 struct sockaddr_in addr;
1126 r = uv_ip4_addr (bind_address, telnet_port, & addr);
1127 if (r == 0)
1128 r = uv_tcp_bind (& fnpData.du_server, (const struct sockaddr *) & addr, 0);
1129 if (r == 0)
1130 r = uv_listen ((uv_stream_t *) & fnpData.du_server, DEFAULT_BACKLOG,
1131 on_new_connection);
1132 if (r)
1133 {
1134 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", bind_address, (long) telnet_port, uv_strerror(r));
1135 close_listener (&fnpData.du_server);
1136 return 1;
1137 }
1138 sim_printf ("\r[FNP emulation: TELNET server listening on %s:%ld]\r\n", bind_address, (long) telnet_port);
1139 return 0;
1140 }
1141
1142
1143
1144 void fnpuvProcessEvent (void)
1145 {
1146
1147
1148
1149
1150
1151
1152
1153
1154 if (! fnpData.loop)
1155 return;
1156 uv_run (fnpData.loop, UV_RUN_NOWAIT);
1157 if (fnp_selecting)
1158 {
1159 const uint64_t now_ns = uv_hrtime ();
1160 for (uvClientData * p = fnp_clients, *next; p; p = next)
1161 {
1162 next = p->next;
1163 if (p->selection_pending && now_ns >= p->selection_deadline_ns &&
1164 !uv_is_closing ((uv_handle_t *)p->client))
1165 close_connection ((uv_stream_t *)p->client);
1166 }
1167 }
1168 }
1169
1170
1171
1172
1173 void fnpuvExit (void)
1174 {
1175
1176
1177 uv_loop_t * loop = fnpData.loop ? fnpData.loop : uv_default_loop ();
1178 if (!loop)
1179 return;
1180
1181 if (fnpData.du_server_inited)
1182 close_listener (&fnpData.du_server);
1183 if (fnpData.du3270_server_inited)
1184 close_listener (&fnpData.du3270_server);
1185
1186 for (uint fnpno = 0; fnpno < N_FNP_UNITS_MAX; fnpno ++)
1187 for (uint lineno = 0; lineno < MAX_LINES; lineno ++)
1188 {
1189 struct t_line * linep = &fnpData.fnpUnitData[fnpno].MState.line[lineno];
1190 if (linep->server.data)
1191 close_listener (&linep->server);
1192 }
1193
1194 for (uvClientData * p = fnp_clients; p; p = p->next)
1195 if (!uv_is_closing ((uv_handle_t *)p->client))
1196 close_connection ((uv_stream_t *)p->client);
1197
1198
1199
1200
1201
1202 for (unsigned int pass = 0;
1203 pass < 128 && (fnp_pending_closes || accessOpenSessions () || pass < 2);
1204 pass ++)
1205 (void)uv_run (loop, UV_RUN_NOWAIT);
1206
1207 if (fnp_pending_closes)
1208 sim_warn ("FNP shutdown: %u pending libuv close callbacks\r\n",
1209 fnp_pending_closes);
1210 if (accessOpenSessions ())
1211 sim_warn ("OPCON shutdown: %u pending libuv close callbacks\r\n",
1212 accessOpenSessions ());
1213 }
1214
1215
1216
1217
1218
1219 static void on_dialout_connect (uv_connect_t * server, int status)
1220 {
1221 sim_printf ("\r[FNP emulation: dialout connect]\r\n");
1222 uv_tcp_t * client = (uv_tcp_t *)server->handle;
1223 uvClientData * p = (uvClientData *)client->data;
1224 FREE (server);
1225
1226 if (! p)
1227 {
1228 sim_printf ("\r[FNP emulation: NOTE: on_dialout_connect called with data == NULL]\r\n");
1229 return;
1230 }
1231 struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
1232 if (linep->line_client != client || uv_is_closing ((uv_handle_t *)client))
1233 return;
1234 if (status < 0)
1235 {
1236 sim_printf ("\r[FNP emulation: dialout connection error: %s]\r\n", uv_strerror(status));
1237
1238
1239 linep->acu_dial_failure = true;
1240 close_connection ((uv_stream_t *)client);
1241 return;
1242 }
1243
1244 fnpuv_cap_send_buffer (client);
1245 fnpuv_read_start (client);
1246 linep->listen = true;
1247 if (linep->lineType == 0)
1248 linep->lineType = 1;
1249 linep->accept_new_terminal = true;
1250 linep->was_CR = false;
1251 if (p->telnetp)
1252 {
1253 ltnDialout (p->telnetp);
1254 }
1255 }
1256
1257
1258
1259
1260
1261 void fnpuv_dial_out (uint fnpno, uint lineno, word36 d1, word36 d2, word36 d3)
1262 {
1263 if (! fnpData.loop)
1264 return;
1265 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1266 return;
1267 sim_printf ("\r[FNP emulation: received dial_out %c.h%03d %012llu %012llu %012llu]\r\n", fnpno+'a', lineno,
1268 (unsigned long long)d1, (unsigned long long)d2, (unsigned long long)d3);
1269 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1270 uint d01 = (d1 >> 30) & 017;
1271 uint d02 = (d1 >> 24) & 017;
1272 uint d03 = (d1 >> 18) & 017;
1273 uint d04 = (d1 >> 12) & 017;
1274 uint d05 = (d1 >> 6) & 017;
1275 uint d06 = (d1 >> 0) & 017;
1276 uint d07 = (d2 >> 30) & 017;
1277 uint d08 = (d2 >> 24) & 017;
1278 uint d09 = (d2 >> 18) & 017;
1279 uint d10 = (d2 >> 12) & 017;
1280 uint d11 = (d2 >> 6) & 017;
1281 uint d12 = (d2 >> 0) & 017;
1282 uint flags = (d3 >> 30) & 017;
1283 uint p1 = (d3 >> 24) & 017;
1284 uint p2 = (d3 >> 18) & 017;
1285 uint p3 = (d3 >> 12) & 017;
1286 uint p4 = (d3 >> 6) & 017;
1287 uint p5 = (d3 >> 0) & 017;
1288
1289 uint oct1 = d01 * 100 + d02 * 10 + d03;
1290 uint oct2 = d04 * 100 + d05 * 10 + d06;
1291 uint oct3 = d07 * 100 + d08 * 10 + d09;
1292 uint oct4 = d10 * 100 + d11 * 10 + d12;
1293
1294 uint port = ((((p1 * 10) + p2) * 10 + p3) * 10 + p4) * 10 + p5;
1295
1296 if (linep->line_client)
1297 {
1298
1299 sim_warn ("dialout requested on an occupied FNP line\r\n");
1300 linep->acu_dial_failure = true;
1301 return;
1302 }
1303
1304
1305
1306 #if defined(TUN)
1307
1308
1309
1310 linep->is_tun = false;
1311 if (flags & 2)
1312 {
1313 if (linep->tun_fd <= 0)
1314 {
1315 char a_name [IFNAMSIZ] = "dps8m";
1316 linep->tun_fd = tun_alloc (a_name);
1317 if (linep->tun_fd < 0)
1318 {
1319 sim_printf ("\r[FNP emulation: dialout TUN tun_alloc returned %d errno %d]\r\n", linep->tun_fd, errno);
1320 return;
1321 }
1322 int flags = fcntl (linep->tun_fd, F_GETFL, 0);
1323 if (flags < 0)
1324 {
1325 sim_printf ("\r[FNP emulation: dialout TUN F_GETFL returned < 0]\r\n");
1326 return;
1327 }
1328 flags |= O_NONBLOCK;
1329 int ret = fcntl (linep->tun_fd, F_SETFL, flags);
1330 if (ret)
1331 {
1332 sim_printf ("\r[FNP emulation: dialout TUN F_SETFL returned %d]\r\n", ret);
1333 return;
1334 }
1335 }
1336 linep->is_tun = true;
1337 return;
1338 }
1339 #endif
1340
1341 if (oct1 > 255 || oct2 > 255 || oct3 > 255 || oct4 > 255 || port > 65535)
1342 {
1343 sim_warn ("dialout requested with invalid address or port\r\n");
1344 linep->acu_dial_failure = true;
1345 return;
1346 }
1347
1348
1349
1350
1351 bool accept = true;
1352 uint32_t ip_addr = (uint32_t) ((oct1 << 24) | (oct2 << 16) | (oct3 << 8) | oct4);
1353 uint this_line = encodeline (fnpno, lineno);
1354 for (int i = 0; i < n_fw_entries; i ++)
1355 {
1356 struct fw_entry_s * p = fw_entries + i;
1357 if (this_line < p->line_0 || this_line > p->line_1)
1358 continue;
1359 if ((ip_addr & p->cidr_mask) != (p->ipaddr & p->cidr_mask))
1360 continue;
1361 accept = p->accept;
1362 break;
1363 }
1364
1365 if (! accept)
1366 {
1367 sim_printf ("Dialout %c.d%03d denied\r\n", fnpno + 'a', lineno);
1368 linep->acu_dial_failure = true;
1369 return;
1370 }
1371
1372 char ipaddr [256];
1373 (void)sprintf (ipaddr, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
1374 sim_printf ("calling %s:%d\r\n", ipaddr,port);
1375
1376 struct sockaddr_in dest;
1377 if (uv_ip4_addr(ipaddr, (int) port, &dest) < 0)
1378 {
1379 linep->acu_dial_failure = true;
1380 return;
1381 }
1382
1383 linep->line_client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1384 if (!linep->line_client)
1385 {
1386 sim_warn ("FNP dialout allocation failed\r\n");
1387 linep->acu_dial_failure = true;
1388 return;
1389 }
1390 int init_rc = uv_tcp_init (fnpData.loop, linep->line_client);
1391 if (init_rc < 0)
1392 {
1393 sim_warn ("dialout TCP initialization failed: %s\r\n", uv_strerror (init_rc));
1394 FREE (linep->line_client);
1395 linep->acu_dial_failure = true;
1396 return;
1397 }
1398 linep->line_client->data = NULL;
1399
1400 uvClientData * p = (uvClientData *) calloc (1, sizeof (uvClientData));
1401 if (! p)
1402 {
1403 sim_warn ("FNP dialout session allocation failed\r\n");
1404 linep->acu_dial_failure = true;
1405 uv_tcp_t * orphan = linep->line_client;
1406 linep->line_client = NULL;
1407 close_unassociated_socket (orphan);
1408 return;
1409 }
1410 p->assoc = true;
1411 p->read_cb = fnpuv_associated_readcb;
1412 p->nPos = 0;
1413 p->ttype = NULL;
1414 p->fnpno = fnpno;
1415 p->lineno = lineno;
1416 register_client (linep->line_client, p);
1417
1418 if (flags & 1)
1419 {
1420 p->write_cb = fnpuv_start_write;
1421 p->write_actual_cb = fnpuv_start_write_actual;
1422 p->telnetp = ltnConnect (linep->line_client);
1423 if (! p->telnetp)
1424 {
1425 sim_warn ("ltnConnect failed\r\n");
1426 linep->acu_dial_failure = true;
1427 close_connection ((uv_stream_t *)linep->line_client);
1428 return;
1429 }
1430 }
1431 else
1432 {
1433 p->write_cb = fnpuv_start_write_actual;
1434 p->write_actual_cb = fnpuv_start_write_actual;
1435 p->telnetp = NULL;
1436 }
1437
1438
1439
1440 uv_connect_t * req = (uv_connect_t *)malloc (sizeof (*req));
1441 if (!req)
1442 {
1443 linep->acu_dial_failure = true;
1444 close_connection ((uv_stream_t *)linep->line_client);
1445 return;
1446 }
1447 int rc = uv_tcp_connect (req, linep->line_client,
1448 (const struct sockaddr *)&dest, on_dialout_connect);
1449 if (rc < 0)
1450 {
1451 sim_warn ("dialout connect failed: %s\r\n", uv_strerror (rc));
1452 linep->acu_dial_failure = true;
1453 FREE (req);
1454 close_connection ((uv_stream_t *)linep->line_client);
1455 }
1456 }
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480 void fnpuv_open_slave (uint fnpno, uint lineno)
1481 {
1482 if (! fnpData.loop)
1483 return;
1484 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1485 return;
1486 sim_printf ("\r[FNP emulation: fnpuv_open_slave %d.%d]\r\n", fnpno, lineno);
1487 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1488
1489
1490 if (linep->server.data)
1491 return;
1492
1493 if (uv_tcp_init (fnpData.loop, & linep->server) < 0)
1494 return;
1495
1496
1497
1498
1499
1500
1501 uvClientData * p = (uvClientData *) calloc (1, sizeof (uvClientData));
1502 if (! p)
1503 {
1504 sim_warn ("FNP slave listener allocation failed\r\n");
1505 linep->server.data = NULL;
1506 close_listener (&linep->server);
1507 return;
1508 }
1509 p->assoc = false;
1510 p->read_cb = fnpuv_associated_readcb;
1511 p->write_cb = fnpuv_start_write_actual;
1512 p->write_actual_cb = fnpuv_start_write_actual;
1513 p->nPos = 0;
1514 p->ttype = NULL;
1515 p->fnpno = fnpno;
1516 p->lineno = lineno;
1517 linep->server.data = p;
1518 linep->line_client = NULL;
1519
1520 struct sockaddr_in addr;
1521 const char * bind_address = fnpData.telnet_address ? fnpData.telnet_address : "0.0.0.0";
1522 int r = uv_ip4_addr (bind_address, linep->port, & addr);
1523 if (r == 0)
1524 r = uv_tcp_bind (& linep->server, (const struct sockaddr *) & addr, 0);
1525 if (r == 0)
1526 r = uv_listen ((uv_stream_t *) & linep->server, DEFAULT_BACKLOG,
1527 on_new_connection);
1528 if (r)
1529 {
1530 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", bind_address, (long) linep->port, uv_strerror(r));
1531 close_listener (&linep->server);
1532 return;
1533 }
1534 sim_printf ("\r[FNP emulation: listening on %s:%ld]\r\n", bind_address, (long) linep->port);
1535 }
1536
1537 #if defined(TUN)
1538 static void processPacketInput (int fnpno, int lineno, unsigned char * buf, ssize_t nread)
1539 {
1540
1541
1542
1543 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1544 {
1545 sim_printf ("\r[FNP emulation: processPacketInput bogus client data]\r\n");
1546 return;
1547 }
1548
1549
1550
1551
1552
1553 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1554 if (nread <= 0 || !buf || (uint64_t)nread > UINT_MAX - linep->inSize ||
1555 (uint64_t)linep->inSize + (uint64_t)nread > 16U * 1024U * 1024U)
1556 {
1557 sim_warn ("TUN input would overflow line buffer; dropping packet\r\n");
1558 return;
1559 }
1560 if (linep->inBuffer)
1561 {
1562 unsigned char * new = realloc (linep->inBuffer, (unsigned long) (linep->inSize + nread));
1563 if (! new)
1564 {
1565 sim_warn ("TUN input allocation failed; dropping packet\r\n");
1566 return;
1567 }
1568 memcpy (new + linep->inSize, buf, (unsigned long) nread);
1569 linep->inSize += nread;
1570 linep->inBuffer = new;
1571 }
1572 else
1573 {
1574 linep->inBuffer = malloc ((unsigned long) nread);
1575 if (! linep->inBuffer)
1576 {
1577 sim_warn ("TUN input allocation failed; dropping packet\r\n");
1578 return;
1579 }
1580 memcpy (linep->inBuffer, buf, (unsigned long) nread);
1581 linep->inSize = (uint) nread;
1582 linep->inUsed = 0;
1583 }
1584
1585 }
1586
1587 static void fnoTUNProcessLine (int fnpno, int lineno, struct t_line * linep)
1588 {
1589
1590 unsigned char buffer [1500 + 16];
1591 ssize_t nread = read (linep->tun_fd, buffer, sizeof (buffer));
1592 if (nread < 0)
1593 {
1594
1595
1596
1597 if (errno == EAGAIN)
1598 return;
1599 sim_printf ("%ld %ld\r\n", (long) nread, (long) errno);
1600 return;
1601 }
1602 if (nread == 0)
1603 return;
1604
1605
1606
1607 unsigned char xbufr [2 * sizeof (buffer) + 1];
1608 static const unsigned char bin2hex [16] = "0123456789ABCDEF";
1609
1610 for (size_t i = 0; i < (size_t)nread; i ++)
1611 {
1612 xbufr [i * 2 + 0] = bin2hex [(buffer [i] >> 4) & 0xf];
1613 xbufr [i * 2 + 1] = bin2hex [(buffer [i] >> 0) & 0xf];
1614 }
1615 xbufr [(size_t)nread * 2] = 0;
1616 processPacketInput (fnpno, lineno, xbufr, nread * 2 + 1);
1617
1618
1619
1620 # define ip 4
1621
1622
1623 if ((size_t)nread < ip + 20)
1624 return;
1625
1626 sim_printf("Read %ld bytes\r\n", (long) nread);
1627 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1628 buffer [0], buffer [1], buffer [2], buffer [3],
1629 buffer [4], buffer [5], buffer [6], buffer [7]);
1630 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1631 buffer [8], buffer [9], buffer [10], buffer [11],
1632 buffer [12], buffer [13], buffer [14], buffer [15]);
1633 uint version = (buffer [ip + 0] >> 4) & 0xf;
1634 uint ihl = (buffer [ip + 0]) & 0xf;
1635 uint payload_offset = ip + ihl * 4;
1636 if (version != 4 || ihl < 5 || payload_offset > (size_t)nread)
1637 return;
1638 uint protocol = buffer [ip + 9];
1639 if (protocol == 1 && payload_offset < (size_t)nread)
1640 {
1641 uint type = buffer [payload_offset + 0];
1642 if (type == 0x08)
1643 {
1644 sim_printf ("ICMP Echo Request %d.%d.%d.%d %d.%d.%d.%d\r\n",
1645 buffer [ip + 12], buffer [ip + 13], buffer [ip + 14], buffer [ip + 15],
1646 buffer [ip + 16], buffer [ip + 17], buffer [ip + 18], buffer [ip + 19]);
1647 }
1648 else
1649 {
1650 sim_printf ("ICMP 0x%02x\r\n", type);
1651 if ((size_t)nread - payload_offset >= 8)
1652 sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\r\n",
1653 buffer [payload_offset + 0], buffer [payload_offset + 1], buffer [payload_offset + 2], buffer [payload_offset + 3],
1654 buffer [payload_offset + 4], buffer [payload_offset + 5], buffer [payload_offset + 6], buffer [payload_offset + 7]);
1655 }
1656 }
1657 if (protocol == 0x11)
1658 {
1659 sim_printf ("UDP\r\n");
1660
1661 }
1662 else
1663 {
1664 sim_printf ("protocol %02x\r\n", protocol);
1665 }
1666 }
1667
1668 void fnpTUNProcessEvent (void)
1669 {
1670 uint numunits = (uint)fnp_dev.numunits;
1671 if (numunits > N_FNP_UNITS_MAX)
1672 numunits = N_FNP_UNITS_MAX;
1673 for (uint fnpno = 0; fnpno < numunits; fnpno ++)
1674 {
1675 for (int lineno = 0; lineno < MAX_LINES; lineno ++)
1676 {
1677 struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1678 if (linep->is_tun)
1679 fnoTUNProcessLine (fnpno, lineno, linep);
1680 }
1681 }
1682 }
1683 #endif
1684
1685 void fnpuv3270Poll (bool start)
1686 {
1687
1688 fnpData.du3270_poll = start ? 100 : 0;
1689 }
1690
1691
1692
1693
1694
1695 static void on_new_3270_connection (uv_stream_t * server, int status)
1696 {
1697 if (status < 0)
1698 {
1699 sim_printf ("\r[FNP emulation: TN3270 new connection error: %s]\r\n", uv_strerror(status));
1700
1701 return;
1702 }
1703
1704 uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1705 if (!client)
1706 {
1707 sim_warn ("TN3270 allocation failed; rejecting connection\r\n");
1708 return;
1709 }
1710
1711 int init_rc = uv_tcp_init (fnpData.loop, client);
1712 if (init_rc < 0)
1713 {
1714 sim_warn ("TN3270 TCP initialization failed: %s\r\n", uv_strerror (init_rc));
1715 FREE (client);
1716 return;
1717 }
1718 client->data = NULL;
1719 if (uv_accept (server, (uv_stream_t *) client) != 0)
1720 {
1721 close_unassociated_socket (client);
1722 return;
1723 }
1724
1725
1726 uint stn_no;
1727 for (stn_no = 0; stn_no < IBM3270_STATIONS_MAX; stn_no ++)
1728 {
1729 if (fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client == NULL)
1730 break;
1731 }
1732 if (stn_no >= IBM3270_STATIONS_MAX)
1733 {
1734
1735 close_unassociated_socket (client);
1736 return;
1737 }
1738
1739 uint fnpno = fnpData.ibm3270ctlr[ASSUME0].fnpno;
1740 uint lineno = fnpData.ibm3270ctlr[ASSUME0].lineno;
1741 if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1742 {
1743 sim_warn ("TN3270 listener has invalid FNP line coordinates\r\n");
1744 close_unassociated_socket (client);
1745 return;
1746 }
1747
1748 fnpData.fnpUnitData[fnpno].MState.line[lineno].line_client = NULL;
1749
1750 fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client = client;
1751
1752
1753 fnpData.ibm3270ctlr[ASSUME0].selDevChar = addr_map[stn_no];
1754
1755 char peer[128];
1756 const char *name = fnpuv_peer_name (client, peer, sizeof (peer));
1757 if (!name)
1758 {
1759 sim_printf ("\r[FNP emulation: CONNECT; address unavailable]\r\n");
1760 }
1761 else
1762 {
1763 sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", name);
1764 }
1765
1766 uvClientData * p = (uvClientData *) calloc (1, sizeof (uvClientData));
1767 if (! p)
1768 {
1769 sim_warn ("TN3270 session allocation failed; closing client\r\n");
1770 fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client = NULL;
1771 close_unassociated_socket (client);
1772 return;
1773 }
1774 register_client (client, p);
1775 p->assoc = false;
1776 p->fnpno = fnpno;
1777 p->lineno = lineno;
1778 p->nPos = 0;
1779 p->ttype = NULL;
1780 p->read_cb = fnpuv_3270_readcb;
1781 p->write_cb = fnpuv_start_3270_write;
1782 p->write_actual_cb = fnpuv_start_write_3270_actual;
1783 p->stationNo = stn_no;
1784 p->telnetp = ltnConnect3270 (client);
1785
1786 if (! p->telnetp)
1787 {
1788 sim_warn ("ltnConnect3270 failed\r\n");
1789 close_connection ((uv_stream_t *)client);
1790 return;
1791 }
1792 fnpuv_read_start (client);
1793 fnp3270ConnectPrompt (client);
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830 }
1831
1832 int fnpuv3270Init (int telnet3270_port)
1833 {
1834 const char * bind_address = fnpData.telnet_address ? fnpData.telnet_address : "0.0.0.0";
1835
1836
1837
1838 if (fnpData.du3270_server_inited)
1839 {
1840 sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
1841 return 1;
1842 }
1843 if (! fnpData.loop)
1844 fnpData.loop = uv_default_loop ();
1845
1846 int r = uv_tcp_init (fnpData.loop, & fnpData.du3270_server);
1847 if (r < 0)
1848 return 1;
1849 fnpData.du3270_server_inited = true;
1850
1851
1852 fnpData.du3270_server.data = NULL;
1853
1854
1855 struct sockaddr_in addr;
1856 r = uv_ip4_addr (bind_address, telnet3270_port, & addr);
1857 if (r == 0)
1858 r = uv_tcp_bind (& fnpData.du3270_server, (const struct sockaddr *) & addr, 0);
1859 if (r == 0)
1860 r = uv_listen ((uv_stream_t *) & fnpData.du3270_server, DEFAULT_BACKLOG,
1861 on_new_3270_connection);
1862 if (r)
1863 {
1864 sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n",
1865 bind_address, (long) telnet3270_port, uv_strerror(r));
1866 close_listener (&fnpData.du3270_server);
1867 return 1;
1868 }
1869 sim_printf ("\r[FNP emulation: TN3270 server listening on %s:%ld]\r\n",
1870 bind_address, (long) telnet3270_port);
1871 fnpuv3270Poll (false);
1872 return 0;
1873 }