source: trunk/FACT++/dim/src/tcpip.c@ 11069

Last change on this file since 11069 was 10614, checked in by tbretz, 13 years ago
New release V19 r20
File size: 33.5 KB
Line 
1/*
2 * DNA (Delphi Network Access) implements the network layer for the DIM
3 * (Delphi Information Managment) System.
4 *
5 * Started : 10-11-91
6 * Last modification : 29-07-94
7 * Written by : C. Gaspar
8 * Adjusted by : G.C. Ballintijn
9 *
10 */
11
12/*
13#define DEBUG
14*/
15
16/* Modifies the number of open connections to 8192 for Windows and Linux */
17/* Can not be moved from here ! */
18#include <dim_tcpip.h>
19
20#ifdef WIN32
21#define ioctl ioctlsocket
22
23#define closesock myclosesocket
24#define readsock recv
25#define writesock send
26
27#define EINTR WSAEINTR
28#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
29#define EWOULDBLOCK WSAEWOULDBLOCK
30#define ECONNREFUSED WSAECONNREFUSED
31#define HOST_NOT_FOUND WSAHOST_NOT_FOUND
32#define NO_DATA WSANO_DATA
33
34#else
35/*
36#define closesock(s) shutdown(s,2);
37*/
38#define closesock close
39#define readsock(a,b,c,d) read(a,b,c)
40
41#if defined(__linux__) && !defined (darwin)
42#define writesock(a,b,c,d) send(a,b,c,MSG_NOSIGNAL)
43#else
44#define writesock(a,b,c,d) write(a,b,c)
45#endif
46
47#ifdef solaris
48#define BSD_COMP
49/*
50#include <thread.h>
51*/
52#endif
53
54#ifdef LYNXOS
55#ifdef RAID
56typedef int pid_t;
57#endif
58#endif
59
60#include <ctype.h>
61#include <sys/socket.h>
62#include <fcntl.h>
63#include <netinet/in.h>
64#include <netinet/tcp.h>
65#include <signal.h>
66#include <sys/ioctl.h>
67#include <errno.h>
68#include <netdb.h>
69#endif
70
71#include <stdio.h>
72#include <time.h>
73#define DIMLIB
74#include <dim.h>
75
76#define ushort unsigned short
77
78static int Threads_on = 0;
79
80static int init_done = FALSE; /* Is this module initialized? */
81static int queue_id = 0;
82
83#ifdef WIN32
84static struct sockaddr_in DIM_sockname;
85#endif
86
87static int DIM_IO_path[2] = {-1,-1};
88static int DIM_IO_Done = 0;
89static int DIM_IO_valid = 1;
90
91static int Write_timeout = 5;
92static int Write_buffer_size = TCP_SND_BUF_SIZE;
93static int Read_buffer_size = TCP_RCV_BUF_SIZE;
94
95int Tcpip_max_io_data_write = TCP_SND_BUF_SIZE - 16;
96int Tcpip_max_io_data_read = TCP_RCV_BUF_SIZE - 16;
97
98void dim_set_write_timeout(int secs)
99{
100 Write_timeout = secs;
101}
102
103int dim_get_write_timeout()
104{
105 return(Write_timeout);
106}
107
108int dim_set_write_buffer_size(int size)
109{
110 if(size >= TCP_SND_BUF_SIZE)
111 {
112 Write_buffer_size = size;
113 Tcpip_max_io_data_write = size - 16;
114 return(1);
115 }
116 return(0);
117}
118
119int dim_get_write_buffer_size()
120{
121 return(Write_buffer_size);
122}
123
124int dim_set_read_buffer_size(int size)
125{
126 if(size >= TCP_RCV_BUF_SIZE)
127 {
128 Read_buffer_size = size;
129 Tcpip_max_io_data_read = size - 16;
130 return(1);
131 }
132 return(0);
133}
134
135int dim_get_read_buffer_size()
136{
137 return(Read_buffer_size);
138}
139
140#ifdef WIN32
141int init_sock()
142{
143 WORD wVersionRequested;
144 WSADATA wsaData;
145 int err;
146 static int sock_init_done = 0;
147
148 if(sock_init_done) return(1);
149 wVersionRequested = MAKEWORD( 2, 0 );
150 err = WSAStartup( wVersionRequested, &wsaData );
151
152 if ( err != 0 )
153 {
154 return(0);
155 }
156
157 /* Confirm that the WinSock DLL supports 2.0.*/
158 /* Note that if the DLL supports versions greater */
159 /* than 2.0 in addition to 2.0, it will still return */
160 /* 2.0 in wVersion since that is the version we */
161 /* requested. */
162
163 if ( LOBYTE( wsaData.wVersion ) != 2 ||
164 HIBYTE( wsaData.wVersion ) != 0 )
165 {
166 WSACleanup( );
167 return(0);
168 }
169 sock_init_done = 1;
170 return(1);
171}
172
173int myclosesocket(int path)
174{
175 int code, ret;
176 code = WSAGetLastError();
177 ret = closesocket(path);
178 WSASetLastError(code);
179 return ret;
180}
181#endif
182
183int dim_tcpip_init(int thr_flag)
184{
185#ifdef WIN32
186 int addr, flags = 1;
187/*
188 void tcpip_task();
189*/
190 void create_io_thread(void);
191#else
192 struct sigaction sig_info;
193 sigset_t set;
194 void io_sig_handler();
195 void dummy_io_sig_handler();
196 void tcpip_pipe_sig_handler();
197#endif
198
199 if(init_done) return(1);
200#ifdef WIN32
201 init_sock();
202 Threads_on = 1;
203#else
204 if(thr_flag)
205 {
206 Threads_on = 1;
207 }
208 else
209 {
210 sigemptyset(&set);
211
212 sigaddset(&set,SIGALRM);
213 sig_info.sa_handler = io_sig_handler;
214 sig_info.sa_mask = set;
215#ifndef LYNXOS
216 sig_info.sa_flags = SA_RESTART;
217#else
218 sig_info.sa_flags = 0;
219#endif
220
221 if( sigaction(SIGIO, &sig_info, 0) < 0 )
222 {
223 perror( "sigaction(SIGIO)" );
224 exit(1);
225 }
226
227 sigemptyset(&set);
228 sig_info.sa_handler = tcpip_pipe_sig_handler;
229 sig_info.sa_mask = set;
230#ifndef LYNXOS
231 sig_info.sa_flags = SA_RESTART;
232#else
233 sig_info.sa_flags = 0;
234#endif
235
236 if( sigaction(SIGPIPE, &sig_info, 0) < 0 ) {
237 perror( "sigaction(SIGPIPE)" );
238 exit(1);
239 }
240
241 }
242#endif
243 if(Threads_on)
244 {
245#ifdef WIN32
246 if(DIM_IO_path[0] == -1)
247 {
248 if( (DIM_IO_path[0] = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
249 {
250 perror("socket");
251 return(0);
252 }
253
254 DIM_sockname.sin_family = PF_INET;
255 addr = 0;
256 DIM_sockname.sin_addr = *((struct in_addr *) &addr);
257 DIM_sockname.sin_port = htons((ushort) 2000);
258 ioctl(DIM_IO_path[0], FIONBIO, &flags);
259 }
260#else
261 if(DIM_IO_path[0] == -1)
262 {
263 pipe(DIM_IO_path);
264 }
265#endif
266 }
267 if(!queue_id)
268 queue_id = dtq_create();
269
270#ifdef WIN32
271/*
272#ifndef STDCALL
273 tid = _beginthread((void *)(void *)tcpip_task,0,NULL);
274#else
275 tid = _beginthreadex(NULL, NULL,
276 tcpip_task,0,0,NULL);
277#endif
278*/
279 create_io_thread();
280#endif
281 init_done = 1;
282 return(1);
283}
284
285void dim_tcpip_stop()
286{
287#ifdef WIN32
288 closesock(DIM_IO_path[0]);
289#else
290 close(DIM_IO_path[0]);
291 close(DIM_IO_path[1]);
292#endif
293 DIM_IO_path[0] = -1;
294 DIM_IO_path[1] = -1;
295 DIM_IO_Done = 0;
296 init_done = 0;
297}
298
299static int enable_sig(int conn_id)
300{
301 int ret = 1, flags = 1;
302#ifndef WIN32
303 int pid;
304#endif
305
306#ifdef DEBUG
307 if(!Net_conns[conn_id].channel)
308 {
309 printf("Enabling signals on channel 0\n");
310 fflush(stdout);
311 }
312#endif
313
314 if(!init_done)
315 {
316 dim_tcpip_init(0);
317 }
318 if(Threads_on)
319 {
320#ifdef WIN32
321 DIM_IO_valid = 0;
322/*
323 ret = connect(DIM_IO_path[0], (struct sockaddr*)&DIM_sockname, sizeof(DIM_sockname));
324*/
325 closesock(DIM_IO_path[0]);
326 DIM_IO_path[0] = -1;
327 if( (DIM_IO_path[0] = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
328 {
329 perror("socket");
330 return(1);
331 }
332 ret = ioctl(DIM_IO_path[0], FIONBIO, &flags);
333 if(ret != 0)
334 {
335 perror("ioctlsocket");
336 }
337 DIM_IO_valid = 1;
338#else
339 if(DIM_IO_path[1] != -1)
340 {
341 if(!DIM_IO_Done)
342 {
343 DIM_IO_Done = 1;
344 write(DIM_IO_path[1], &flags, 4);
345 }
346 }
347#endif
348 }
349#ifndef WIN32
350 if(!Threads_on)
351 {
352 pid = getpid();
353
354#ifndef __linux__
355 ret = ioctl(Net_conns[conn_id].channel, SIOCSPGRP, &pid );
356#else
357 ret = fcntl(Net_conns[conn_id].channel,F_SETOWN, pid);
358#endif
359 if(ret == -1)
360 {
361#ifdef DEBUG
362 printf("ioctl returned -1\n");
363#endif
364 return(ret);
365 }
366 }
367 ret = ioctl(Net_conns[conn_id].channel, FIOASYNC, &flags );
368 if(ret == -1)
369 {
370#ifdef DEBUG
371 printf("ioctl1 returned -1\n");
372#endif
373 return(ret);
374 }
375
376 flags = fcntl(Net_conns[conn_id].channel,F_GETFD,0);
377#ifdef DEBUG
378 if(flags == -1)
379 {
380 printf("error\n");
381 }
382#endif
383 ret = fcntl(Net_conns[conn_id].channel,F_SETFD, flags | FD_CLOEXEC );
384 if(ret == -1)
385 {
386#ifdef DEBUG
387 printf("ioctl2 returned -1\n");
388#endif
389 return(ret);
390 }
391#endif
392 return(1);
393}
394
395/*
396static void dump_list()
397{
398 int i;
399
400 for( i = 1; i < Curr_N_Conns; i++ )
401 if( Dna_conns[i].busy ) {
402 printf( "dump_list: conn_id=%d reading=%d\n",
403 i, Net_conns[i].reading );
404 }
405}
406*/
407
408static int list_to_fds( fd_set *fds )
409{
410 int i;
411 int found = 0;
412
413 FD_ZERO( fds ) ;
414 for( i = 1; i < Curr_N_Conns; i++ )
415 {
416 if( Dna_conns[i].busy )
417 {
418 if(Net_conns[i].channel)
419 {
420 found = 1;
421 FD_SET( Net_conns[i].channel, fds );
422
423 }
424 }
425 }
426 return(found);
427}
428
429static int fds_get_entry( fd_set *fds, int *conn_id )
430{
431 int i;
432
433 for( i = 1; i < Curr_N_Conns; i++ )
434 {
435 if( Dna_conns[i].busy &&
436 FD_ISSET(Net_conns[i].channel, fds) )
437 {
438 if(Net_conns[i].channel)
439 {
440 *conn_id = i;
441 return 1;
442 }
443 }
444 }
445 return 0;
446}
447
448#if defined(__linux__) && !defined (darwin)
449
450void tcpip_set_keepalive( int channel, int tmout )
451{
452 int val;
453
454 /* Enable keepalive for the given channel */
455 val = 1;
456 setsockopt(channel, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val));
457
458 /* Set the keepalive poll interval to something small.
459 Warning: this section may not be portable! */
460 val = tmout;
461 setsockopt(channel, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&val, sizeof(val));
462 val = 3;
463 setsockopt(channel, IPPROTO_TCP, TCP_KEEPCNT, (char*)&val, sizeof(val));
464 val = 2;
465 setsockopt(channel, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&val, sizeof(val));
466}
467
468#else
469
470static void tcpip_test_write( int conn_id )
471{
472 /* Write to every socket we use, which uses the TCPIP protocol,
473 * which has an established connection (reading), which is currently
474 * not writing data, so we can check if it is still alive.
475 */
476 time_t cur_time;
477
478 if(strcmp(Net_conns[conn_id].node,"MYNODE"))
479 {
480 cur_time = time(NULL);
481 if( cur_time - Net_conns[conn_id].last_used > Net_conns[conn_id].timeout )
482 {
483 dna_test_write( conn_id );
484 }
485 }
486}
487
488#endif
489
490void tcpip_set_test_write(int conn_id, int timeout)
491{
492#if defined(__linux__) && !defined (darwin)
493 tcpip_set_keepalive(Net_conns[conn_id].channel, timeout);
494#else
495 Net_conns[conn_id].timr_ent = dtq_add_entry( queue_id, timeout,
496 tcpip_test_write, conn_id );
497 Net_conns[conn_id].timeout = timeout;
498 Net_conns[conn_id].last_used = time(NULL);
499#endif
500}
501
502void tcpip_rem_test_write(int conn_id)
503{
504 if(Net_conns[conn_id].timr_ent)
505 {
506 dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
507 Net_conns[conn_id].timr_ent = NULL;
508 }
509 Net_conns[conn_id].last_used = time(NULL);
510}
511
512void tcpip_pipe_sig_handler( int num )
513{
514 if(num){}
515/*
516 printf( "*** pipe_sig_handler called ***\n" );
517*/
518}
519
520static int get_bytes_to_read(int conn_id)
521{
522 int i, ret, count;
523
524 for(i = 0; i < 3; i++)
525 {
526 ret = ioctl( Net_conns[conn_id].channel, FIONREAD, &count );
527 if( ret != 0)
528 {
529 count = 0;
530 break;
531 }
532 if(count > 0)
533 {
534 break;
535 }
536 }
537 return(count);
538}
539
540static int do_read( int conn_id )
541{
542 /* There is 'data' pending, read it.
543 */
544 int len, totlen, size, count;
545 char *p;
546
547 count = get_bytes_to_read(conn_id);
548 if(!count)
549 {
550/*
551 dna_report_error(conn_id, -1,
552 "Connection closed by remote peer", DIM_ERROR, DIMTCPRDERR);
553 printf("conn_id %d\n", conn_id);
554*/
555 Net_conns[conn_id].read_rout( conn_id, -1, 0 );
556 return 0;
557 }
558
559 size = Net_conns[conn_id].size;
560 p = Net_conns[conn_id].buffer;
561 totlen = 0;
562/*
563 count = 1;
564*/
565 while( size > 0 && count > 0 )
566 {
567/*
568 would this be better? not sure afterwards...
569 nbytes = (size < count) ? size : count;
570 if( (len = readsock(Net_conns[conn_id].channel, p, nbytes, 0)) <= 0 )
571*/
572 if( (len = readsock(Net_conns[conn_id].channel, p, size, 0)) <= 0 )
573 { /* Connection closed by other side. */
574 Net_conns[conn_id].read_rout( conn_id, -1, 0 );
575 return 0;
576 }
577 else
578 {
579
580 /*
581 printf("tcpip: read %d bytes:\n",len);
582 printf( "buffer[0]=%d\n", vtohl((int *)p[0]));
583 printf( "buffer[1]=%d\n", vtohl((int *)p[1]));
584 printf( "buffer[2]=%x\n", vtohl((int *)p[2]));
585 */
586 totlen += len;
587 size -= len;
588 p += len;
589 }
590 if(size)
591 count = get_bytes_to_read(conn_id);
592 }
593
594 Net_conns[conn_id].last_used = time(NULL);
595 Net_conns[conn_id].read_rout( conn_id, 1, totlen );
596 return 1;
597}
598
599
600void do_accept( int conn_id )
601{
602 /* There is a 'connect' pending, serve it.
603 */
604 struct sockaddr_in other;
605 int othersize;
606
607 othersize = sizeof(other);
608 memset( (char *) &other, 0, othersize );
609 Net_conns[conn_id].mbx_channel = accept( Net_conns[conn_id].channel,
610 (struct sockaddr*)&other, (unsigned int *)&othersize );
611 if( Net_conns[conn_id].mbx_channel < 0 )
612 {
613 return;
614 }
615/*
616 else
617 {
618 int all, a, b, c, d;
619 char *pall;
620
621 all = other.sin_addr.s_addr;
622 pall = &all;
623 a = pall[0];
624 a &= 0x000000ff;
625 b = pall[1];
626 b &= 0x000000ff;
627 c = pall[2];
628 c &= 0x000000ff;
629 d = pall[3];
630 d &= 0x000000ff;
631printf("TCPIP got %d.%d.%d.%d \n",
632 a,b,c,d);
633 if((a == 134) && (b == 79) && (c == 157) && (d == 40))
634 {
635 closesock(Net_conns[conn_id].mbx_channel);
636 return;
637 }
638 }
639*/
640
641 Net_conns[conn_id].last_used = time(NULL);
642 Net_conns[conn_id].read_rout( Net_conns[conn_id].mbx_channel,
643 conn_id, TCPIP );
644}
645
646void io_sig_handler(int num)
647{
648 fd_set rfds;
649 int conn_id, ret, selret, count;
650 struct timeval timeout;
651
652 if(num){}
653 do
654 {
655 timeout.tv_sec = 0; /* Don't wait, just poll */
656 timeout.tv_usec = 0;
657 list_to_fds( &rfds );
658 selret = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout);
659 if(selret > 0)
660 {
661 while( (ret = fds_get_entry( &rfds, &conn_id )) > 0 )
662 {
663 if( Net_conns[conn_id].reading )
664 {
665 count = 0;
666 do
667 {
668 if(Net_conns[conn_id].channel)
669 {
670 do_read( conn_id );
671 count = get_bytes_to_read(conn_id);
672 }
673 else
674 {
675 count = 0;
676 }
677 }while(count > 0 );
678 }
679 else
680 {
681 do_accept( conn_id );
682 }
683 FD_CLR( (unsigned)Net_conns[conn_id].channel, &rfds );
684 }
685 }
686 }while(selret > 0);
687}
688
689void tcpip_task( void *dummy)
690{
691 /* wait for an IO signal, find out what is happening and
692 * call the right routine to handle the situation.
693 */
694 fd_set rfds, efds, *pfds;
695 int conn_id, ret, count;
696#ifndef WIN32
697 int data;
698#endif
699 if(dummy){}
700 while(1)
701 {
702 while(!DIM_IO_valid)
703 dim_usleep(1000);
704
705 list_to_fds( &rfds );
706 FD_ZERO(&efds);
707#ifdef WIN32
708 pfds = &efds;
709#else
710 pfds = &rfds;
711#endif
712 FD_SET( DIM_IO_path[0], pfds );
713 ret = select(FD_SETSIZE, &rfds, NULL, &efds, NULL);
714 if(ret > 0)
715 {
716 if(FD_ISSET(DIM_IO_path[0], pfds) )
717 {
718#ifndef WIN32
719 read(DIM_IO_path[0], &data, 4);
720 DIM_IO_Done = 0;
721#endif
722 FD_CLR( (unsigned)DIM_IO_path[0], pfds );
723 }
724/*
725 {
726 DISABLE_AST
727*/
728 while( (ret = fds_get_entry( &rfds, &conn_id )) > 0 )
729 {
730 if( Net_conns[conn_id].reading )
731 {
732 count = 0;
733 do
734 {
735 DISABLE_AST
736 if(Net_conns[conn_id].channel)
737 {
738 do_read( conn_id );
739 count = get_bytes_to_read(conn_id);
740 }
741 else
742 {
743 count = 0;
744 }
745 ENABLE_AST
746 }while(count > 0 );
747 }
748 else
749 {
750 DISABLE_AST
751 do_accept( conn_id );
752 ENABLE_AST
753 }
754 FD_CLR( (unsigned)Net_conns[conn_id].channel, &rfds );
755 }
756/*
757 ENABLE_AST
758 }
759*/
760#ifndef WIN32
761 return;
762#endif
763 }
764 }
765}
766
767int tcpip_start_read( int conn_id, char *buffer, int size, void (*ast_routine)() )
768{
769 /* Install signal handler stuff on the socket, and record
770 * some necessary information: we are reading, and want size
771 * as size, and use buffer.
772 */
773
774 Net_conns[conn_id].read_rout = ast_routine;
775 Net_conns[conn_id].buffer = buffer;
776 Net_conns[conn_id].size = size;
777 if(Net_conns[conn_id].reading == -1)
778 {
779 if(enable_sig( conn_id ) == -1)
780 {
781#ifdef DEBUG
782 printf("START_READ - enable_sig returned -1\n");
783#endif
784 return(0);
785 }
786 }
787 Net_conns[conn_id].reading = TRUE;
788 return(1);
789}
790
791int check_node_addr( char *node, unsigned char *ipaddr)
792{
793unsigned char *ptr;
794int ret;
795
796 ptr = (unsigned char *)node+strlen(node)+1;
797 ipaddr[0] = *ptr++;
798 ipaddr[1] = *ptr++;
799 ipaddr[2] = *ptr++;
800 ipaddr[3] = *ptr++;
801 if( (ipaddr[0] == 0xff) &&
802 (ipaddr[1] == 0xff) &&
803 (ipaddr[2] == 0xff) &&
804 (ipaddr[3] == 0xff) )
805 {
806 errno = ECONNREFUSED; /* fake an error code */
807#ifdef WIN32
808 WSASetLastError(errno);
809#endif
810 return(0);
811 }
812 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
813 {
814#ifndef WIN32
815 ret = h_errno;
816#else
817 ret = WSAGetLastError();
818#endif
819 if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
820 return(0);
821/*
822 errno = ECONNREFUSED;
823#ifdef WIN32
824 WSASetLastError(errno);
825#endif
826 return(0);
827*/
828 }
829 return(1);
830}
831
832int tcpip_open_client( int conn_id, char *node, char *task, int port )
833{
834 /* Create connection: create and initialize socket stuff. Try
835 * and make a connection with the server.
836 */
837 struct sockaddr_in sockname;
838#ifndef VxWorks
839 struct hostent *host = 0;
840#else
841 int host_addr;
842#endif
843 int path, val, ret_code, ret;
844 int a,b,c,d;
845 unsigned char ipaddr[4];
846 int host_number = 0;
847
848 dim_tcpip_init(0);
849 if(isdigit(node[0]))
850 {
851 sscanf(node,"%d.%d.%d.%d",&a, &b, &c, &d);
852 ipaddr[0] = a;
853 ipaddr[1] = b;
854 ipaddr[2] = c;
855 ipaddr[3] = d;
856 host_number = 1;
857#ifndef VxWorks
858 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
859 {
860#ifndef WIN32
861 ret = h_errno;
862#else
863 ret = WSAGetLastError();
864#endif
865 if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
866 {
867 if(!check_node_addr(node, ipaddr))
868 return(0);
869 }
870 }
871#endif
872 }
873#ifndef VxWorks
874 else if( (host = gethostbyname(node)) == (struct hostent *)0 )
875 {
876 if(!check_node_addr(node, ipaddr))
877 return(0);
878 host_number = 1;
879/*
880 ptr = (unsigned char *)node+strlen(node)+1;
881 ipaddr[0] = *ptr++;
882 ipaddr[1] = *ptr++;
883 ipaddr[2] = *ptr++;
884 ipaddr[3] = *ptr++;
885 host_number = 1;
886 if( (ipaddr[0] == 0xff) &&
887 (ipaddr[1] == 0xff) &&
888 (ipaddr[2] == 0xff) &&
889 (ipaddr[3] == 0xff) )
890 {
891 errno = ECONNREFUSED;
892#ifdef WIN32
893 WSASetLastError(errno);
894#endif
895 return(0);
896 }
897 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
898 {
899 errno = ECONNREFUSED;
900#ifdef WIN32
901 WSASetLastError(errno);
902#endif
903 return(0);
904 }
905*/
906 }
907#else
908 *(strchr(node,'.')) = '\0';
909 host_addr = hostGetByName(node);
910 printf("node %s addr: %x\n",node, host_addr);
911#endif
912
913 if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
914 {
915 perror("socket");
916 return(0);
917 }
918
919 val = 1;
920
921 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
922 (char*)&val, sizeof(val))) == -1 )
923 {
924#ifdef DEBUG
925 printf("Couln't set TCP_NODELAY\n");
926#endif
927 closesock(path);
928 return(0);
929 }
930
931 val = Write_buffer_size;
932 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
933 (char*)&val, sizeof(val))) == -1 )
934 {
935#ifdef DEBUG
936 printf("Couln't set SO_SNDBUF\n");
937#endif
938 closesock(path);
939 return(0);
940 }
941
942 val = Read_buffer_size;
943 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
944 (char*)&val, sizeof(val))) == -1 )
945 {
946#ifdef DEBUG
947 printf("Couln't set SO_RCVBUF\n");
948#endif
949 closesock(path);
950 return(0);
951 }
952
953#if defined(__linux__) && !defined (darwin)
954 val = 2;
955 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_SYNCNT,
956 (char*)&val, sizeof(val))) == -1 )
957 {
958#ifdef DEBUG
959 printf("Couln't set TCP_SYNCNT\n");
960#endif
961 }
962#endif
963
964 sockname.sin_family = PF_INET;
965#ifndef VxWorks
966 if(host_number)
967 sockname.sin_addr = *((struct in_addr *) ipaddr);
968 else
969 sockname.sin_addr = *((struct in_addr *) host->h_addr);
970#else
971 if(host_number)
972 sockname.sin_addr = *((struct in_addr *) ipaddr);
973 else
974 sockname.sin_addr = *((struct in_addr *) &host_addr);
975#endif
976 sockname.sin_port = htons((ushort) port); /* port number to send to */
977 while((ret = connect(path, (struct sockaddr*)&sockname, sizeof(sockname))) == -1 )
978 {
979 if(errno != EINTR)
980 {
981 closesock(path);
982 return(0);
983 }
984 }
985 strcpy( Net_conns[conn_id].node, node );
986 strcpy( Net_conns[conn_id].task, task );
987 Net_conns[conn_id].channel = path;
988 Net_conns[conn_id].port = port;
989 Net_conns[conn_id].last_used = time(NULL);
990 Net_conns[conn_id].reading = -1;
991 Net_conns[conn_id].timr_ent = NULL;
992 return(1);
993}
994
995int tcpip_open_server( int conn_id, char *task, int *port )
996{
997 /* Create connection: create and initialize socket stuff,
998 * find a free port on this node.
999 */
1000 struct sockaddr_in sockname;
1001 int path, val, ret_code, ret;
1002
1003 dim_tcpip_init(0);
1004 if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
1005 {
1006 return(0);
1007 }
1008
1009 val = 1;
1010 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1011 (char*)&val, sizeof(val))) == -1 )
1012
1013 {
1014#ifdef DEBUG
1015 printf("Couln't set TCP_NODELAY\n");
1016#endif
1017 closesock(path);
1018 return(0);
1019 }
1020
1021 val = Write_buffer_size;
1022 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1023 (void *)&val, sizeof(val))) == -1 )
1024 {
1025#ifdef DEBUG
1026 printf("Couln't set SO_SNDBUF\n");
1027#endif
1028 closesock(path);
1029 return(0);
1030 }
1031/*
1032 sval1 = sizeof(val1);
1033 if ((ret_code = getsockopt(path, SOL_SOCKET, SO_SNDBUF,
1034 (void *)&val1, &sval1)) == -1 )
1035 {
1036#ifdef DEBUG
1037 printf("Couln't set SO_SNDBUF\n");
1038#endif
1039 closesock(path);
1040 return(0);
1041 }
1042printf("Set size to %d, got size %d\n", val, val1);
1043*/
1044 val = Read_buffer_size;
1045 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1046 (void *)&val, sizeof(val))) == -1 )
1047 {
1048#ifdef DEBUG
1049 printf("Couln't set SO_RCVBUF\n");
1050#endif
1051 closesock(path);
1052 return(0);
1053 }
1054
1055 if( *port == SEEK_PORT )
1056 { /* Search a free one. */
1057 *port = START_PORT_RANGE - 1;
1058 do
1059 {
1060 (*port)++;
1061 sockname.sin_family = AF_INET;
1062 sockname.sin_addr.s_addr = INADDR_ANY;
1063 sockname.sin_port = htons((ushort) *port);
1064 if( *port > STOP_PORT_RANGE ) {
1065 errno = EADDRNOTAVAIL; /* fake an error code */
1066 closesock(path);
1067#ifdef WIN32
1068 WSASetLastError(errno);
1069#endif
1070 return(0);
1071 }
1072 ret = bind(path, (struct sockaddr*)&sockname, sizeof(sockname));
1073/*
1074printf("Trying port %d, ret = %d\n", *port, ret);
1075*/
1076 } while( ret == -1 );
1077/*
1078 } while( bind(path, (struct sockaddr*)&sockname, sizeof(sockname)) == -1 );
1079*/
1080 } else {
1081#ifndef WIN32
1082 val = 1;
1083 if( setsockopt(path, SOL_SOCKET, SO_REUSEADDR, (char*)&val,
1084 sizeof(val)) == -1 )
1085 {
1086#ifdef DEBUG
1087 printf("Couln't set SO_REUSEADDR\n");
1088#endif
1089 closesock(path);
1090 return(0);
1091 }
1092#endif
1093 sockname.sin_family = AF_INET;
1094 sockname.sin_addr.s_addr = INADDR_ANY;
1095 sockname.sin_port = htons((ushort) *port);
1096 if( (ret = bind(path, (struct sockaddr*) &sockname, sizeof(sockname))) == -1 )
1097 {
1098 closesock(path);
1099 return(0);
1100 }
1101 }
1102
1103 if( (ret = listen(path, SOMAXCONN)) == -1 )
1104 {
1105 closesock(path);
1106 return(0);
1107 }
1108
1109 strcpy( Net_conns[conn_id].node, "MYNODE" );
1110 strcpy( Net_conns[conn_id].task, task );
1111 Net_conns[conn_id].channel = path;
1112 Net_conns[conn_id].port = *port;
1113 Net_conns[conn_id].last_used = time(NULL);
1114 Net_conns[conn_id].reading = -1;
1115 Net_conns[conn_id].timr_ent = NULL;
1116 return(1);
1117}
1118
1119
1120int tcpip_start_listen( int conn_id, void (*ast_routine)() )
1121{
1122 /* Install signal handler stuff on the socket, and record
1123 * some necessary information: we are NOT reading, thus
1124 * no size.
1125 */
1126
1127 Net_conns[conn_id].read_rout = ast_routine;
1128 Net_conns[conn_id].size = -1;
1129 if(Net_conns[conn_id].reading == -1)
1130 {
1131 if(enable_sig( conn_id ) == -1)
1132 {
1133#ifdef DEBUG
1134 printf("START_LISTEN - enable_sig returned -1\n");
1135#endif
1136 return(0);
1137 }
1138 }
1139 Net_conns[conn_id].reading = FALSE;
1140 return(1);
1141}
1142
1143
1144int tcpip_open_connection( int conn_id, int path )
1145{
1146 /* Fill in/clear some fields, the node and task field
1147 * get filled in later by a special packet.
1148 */
1149 int val, ret_code;
1150
1151
1152 val = 1;
1153 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1154 (char*)&val, sizeof(val))) == -1 )
1155 {
1156#ifdef DEBUG
1157 printf("Couln't set TCP_NODELAY\n");
1158#endif
1159 closesock(path);
1160 return(0);
1161 }
1162 val = Write_buffer_size;
1163 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1164 (char*)&val, sizeof(val))) == -1 )
1165 {
1166#ifdef DEBUG
1167 printf("Couln't set SO_SNDBUF\n");
1168#endif
1169 closesock(path);
1170 return(0);
1171 }
1172
1173 val = Read_buffer_size;
1174 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1175 (char*)&val, sizeof(val))) == -1 )
1176 {
1177#ifdef DEBUG
1178 printf("Couln't set SO_RCVBUF\n");
1179#endif
1180 closesock(path);
1181 return(0);
1182 }
1183
1184 Net_conns[conn_id].channel = path;
1185 Net_conns[conn_id].node[0] = 0;
1186 Net_conns[conn_id].task[0] = 0;
1187 Net_conns[conn_id].port = 0;
1188 Net_conns[conn_id].reading = -1;
1189 Net_conns[conn_id].timr_ent = NULL;
1190 return(1);
1191}
1192
1193
1194void tcpip_get_node_task( int conn_id, char *node, char *task )
1195{
1196 strcpy( node, Net_conns[conn_id].node );
1197 strcpy( task, Net_conns[conn_id].task );
1198}
1199
1200int tcpip_write( int conn_id, char *buffer, int size )
1201{
1202 /* Do a (synchronous) write to conn_id.
1203 */
1204 int wrote;
1205
1206 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1207 if( wrote == -1 ) {
1208/*
1209 Net_conns[conn_id].read_rout( conn_id, -1, 0 );
1210*/
1211 return(0);
1212 }
1213 return(wrote);
1214}
1215
1216int set_non_blocking(int channel)
1217{
1218 int ret, flags = 1;
1219 ret = ioctl(channel, FIONBIO, &flags );
1220 if(ret == -1)
1221 {
1222#ifdef DEBUG
1223 printf("ioctl non block returned -1\n");
1224#endif
1225 return(ret);
1226 }
1227 return(1);
1228}
1229
1230int set_blocking(int channel)
1231{
1232 int ret, flags = 0;
1233 ret = ioctl(channel, FIONBIO, &flags );
1234 if(ret == -1)
1235 {
1236#ifdef DEBUG
1237 printf("ioctl block returned -1\n");
1238#endif
1239 return(ret);
1240 }
1241 return(1);
1242}
1243
1244int tcpip_write_nowait( int conn_id, char *buffer, int size )
1245{
1246 /* Do a (asynchronous) write to conn_id.
1247 */
1248 int wrote, ret, selret;
1249
1250 struct timeval timeout;
1251 fd_set wfds;
1252 int tcpip_would_block();
1253
1254 set_non_blocking(Net_conns[conn_id].channel);
1255 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1256#ifndef WIN32
1257 ret = errno;
1258#else
1259 ret = WSAGetLastError();
1260#endif
1261 set_blocking(Net_conns[conn_id].channel);
1262 if(wrote == -1)
1263 {
1264 if(tcpip_would_block(ret))
1265 {
1266 timeout.tv_sec = Write_timeout;
1267 timeout.tv_usec = 0;
1268 FD_ZERO(&wfds);
1269 FD_SET( Net_conns[conn_id].channel, &wfds);
1270 selret = select(FD_SETSIZE, NULL, &wfds, NULL, &timeout);
1271 if(selret > 0)
1272 {
1273 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1274 if( wrote == -1 )
1275 {
1276 return(0);
1277 }
1278 }
1279 }
1280 else
1281 return(0);
1282 }
1283 return(wrote);
1284}
1285
1286int tcpip_close( int conn_id )
1287{
1288 int channel;
1289 /* Clear all traces of the connection conn_id.
1290 */
1291 if(Net_conns[conn_id].timr_ent)
1292 {
1293 dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
1294 Net_conns[conn_id].timr_ent = NULL;
1295 }
1296 channel = Net_conns[conn_id].channel;
1297 Net_conns[conn_id].channel = 0;
1298 Net_conns[conn_id].port = 0;
1299 Net_conns[conn_id].node[0] = 0;
1300 Net_conns[conn_id].task[0] = 0;
1301 if(channel)
1302 closesock(channel);
1303 return(1);
1304}
1305
1306
1307int tcpip_failure( int code )
1308{
1309 return(!code);
1310}
1311
1312int tcpip_would_block( int code )
1313{
1314 if(code == EWOULDBLOCK)
1315 return(1);
1316 return(0);
1317}
1318
1319void tcpip_report_error( int code )
1320{
1321#ifndef WIN32
1322 if(code){}
1323 perror("tcpip");
1324#else
1325 int my_perror();
1326
1327 my_perror("tcpip", code);
1328#endif
1329}
1330
1331#ifdef WIN32
1332int my_perror(char *str, int error)
1333{
1334int code;
1335
1336 if(error <= 0)
1337 code = WSAGetLastError();
1338 else
1339 code = error;
1340 printf("new - %s\n",strerror(code));
1341 printf("%s: ",str);
1342 switch(code)
1343 {
1344 case WSAEWOULDBLOCK:
1345 printf("Operation would block");
1346 break;
1347 case WSAEINPROGRESS:
1348 printf("Operation now in progress");
1349 break;
1350 case WSAEALREADY:
1351 printf("Operation already in progress");
1352 break;
1353 case WSAENOTSOCK:
1354 printf("Socket operation on non-socket");
1355 break;
1356 case WSAEDESTADDRREQ:
1357 printf("Destination address required");
1358 break;
1359 case WSAEMSGSIZE:
1360 printf("Message too long");
1361 break;
1362 case WSAEPROTOTYPE:
1363 printf("Protocol wrong type for socket");
1364 break;
1365 case WSAENOPROTOOPT:
1366 printf("Protocol not available");
1367 break;
1368 case WSAEPROTONOSUPPORT:
1369 printf("Protocol not supported");
1370 break;
1371 case WSAESOCKTNOSUPPORT:
1372 printf("Socket type not supported");
1373 break;
1374 case WSAEOPNOTSUPP:
1375 printf("Operation not supported on transport endpoint");
1376 break;
1377 case WSAEPFNOSUPPORT:
1378 printf("Protocol family not supported");
1379 break;
1380 case WSAEAFNOSUPPORT:
1381 printf("Address family not supported by protocol");
1382 break;
1383 case WSAEADDRINUSE:
1384 printf("Address already in use");
1385 break;
1386 case WSAEADDRNOTAVAIL:
1387 printf("Cannot assign requested address");
1388 break;
1389 case WSAENETDOWN:
1390 printf("Network is down");
1391 break;
1392 case WSAENETUNREACH:
1393 printf("Network is unreachable");
1394 break;
1395 case WSAENETRESET:
1396 printf("Network dropped connection because of reset");
1397 break;
1398 case WSAECONNABORTED:
1399 printf("Software caused connection abort");
1400 break;
1401 case WSAECONNRESET:
1402 printf("Connection reset by peer");
1403 break;
1404 case WSAENOBUFS:
1405 printf("No buffer space available");
1406 break;
1407 case WSAEISCONN:
1408 printf("Transport endpoint is already connected");
1409 break;
1410 case WSAENOTCONN:
1411 printf("Transport endpoint is not connected");
1412 break;
1413 case WSAESHUTDOWN:
1414 printf("Cannot send after transport endpoint shutdown");
1415 break;
1416 case WSAETOOMANYREFS:
1417 printf("Too many references: cannot splice");
1418 break;
1419 case WSAETIMEDOUT:
1420 printf("Connection timed out");
1421 break;
1422 case WSAECONNREFUSED:
1423 printf("Connection refused");
1424 break;
1425 case WSAELOOP:
1426 printf("Too many symbolic links encountered");
1427 break;
1428 case WSAENAMETOOLONG:
1429 printf("File name too long");
1430 break;
1431 case WSAEHOSTDOWN:
1432 printf("Host is down");
1433 break;
1434 case WSAEHOSTUNREACH:
1435 printf("No route to host");
1436 break;
1437 case WSAENOTEMPTY:
1438 printf("Directory not empty");
1439 break;
1440 case WSAEUSERS:
1441 printf("Too many users");
1442 break;
1443 case WSAEDQUOT:
1444 printf("Quota exceeded");
1445 break;
1446 case WSAESTALE:
1447 printf("Stale NFS file handle");
1448 break;
1449 case WSAEREMOTE:
1450 printf("Object is remote");
1451 break;
1452 case WSAHOST_NOT_FOUND:
1453 printf("Host not found");
1454 break;
1455 case WSATRY_AGAIN:
1456 printf("Host not found, or SERVERFAIL");
1457 break;
1458 case WSANO_RECOVERY:
1459 printf("Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1460 break;
1461 case WSANO_DATA:
1462 printf("Valid name, no data record of requested type");
1463 break;
1464 default:
1465 printf("Unknown error %d",code);
1466 }
1467 printf("\n");
1468 return(1);
1469}
1470
1471void my_strerror(int error, char *msg)
1472{
1473int code;
1474char str[128];
1475
1476 if(error <= 0)
1477 code = WSAGetLastError();
1478 else
1479 code = error;
1480 switch(code)
1481 {
1482 case WSAEWOULDBLOCK:
1483 sprintf(str,"Operation would block");
1484 break;
1485 case WSAEINPROGRESS:
1486 sprintf(str,"Operation now in progress");
1487 break;
1488 case WSAEALREADY:
1489 sprintf(str,"Operation already in progress");
1490 break;
1491 case WSAENOTSOCK:
1492 sprintf(str,"Socket operation on non-socket");
1493 break;
1494 case WSAEDESTADDRREQ:
1495 sprintf(str,"Destination address required");
1496 break;
1497 case WSAEMSGSIZE:
1498 sprintf(str,"Message too long");
1499 break;
1500 case WSAEPROTOTYPE:
1501 sprintf(str,"Protocol wrong type for socket");
1502 break;
1503 case WSAENOPROTOOPT:
1504 sprintf(str,"Protocol not available");
1505 break;
1506 case WSAEPROTONOSUPPORT:
1507 sprintf(str,"Protocol not supported");
1508 break;
1509 case WSAESOCKTNOSUPPORT:
1510 sprintf(str,"Socket type not supported");
1511 break;
1512 case WSAEOPNOTSUPP:
1513 sprintf(str,"Operation not supported on transport endpoint");
1514 break;
1515 case WSAEPFNOSUPPORT:
1516 sprintf(str,"Protocol family not supported");
1517 break;
1518 case WSAEAFNOSUPPORT:
1519 sprintf(str,"Address family not supported by protocol");
1520 break;
1521 case WSAEADDRINUSE:
1522 sprintf(str,"Address already in use");
1523 break;
1524 case WSAEADDRNOTAVAIL:
1525 sprintf(str,"Cannot assign requested address");
1526 break;
1527 case WSAENETDOWN:
1528 sprintf(str,"Network is down");
1529 break;
1530 case WSAENETUNREACH:
1531 sprintf(str,"Network is unreachable");
1532 break;
1533 case WSAENETRESET:
1534 sprintf(str,"Network dropped connection because of reset");
1535 break;
1536 case WSAECONNABORTED:
1537 sprintf(str,"Software caused connection abort");
1538 break;
1539 case WSAECONNRESET:
1540 sprintf(str,"Connection reset by peer");
1541 break;
1542 case WSAENOBUFS:
1543 sprintf(str,"No buffer space available");
1544 break;
1545 case WSAEISCONN:
1546 sprintf(str,"Transport endpoint is already connected");
1547 break;
1548 case WSAENOTCONN:
1549 sprintf(str,"Transport endpoint is not connected");
1550 break;
1551 case WSAESHUTDOWN:
1552 sprintf(str,"Cannot send after transport endpoint shutdown");
1553 break;
1554 case WSAETOOMANYREFS:
1555 sprintf(str,"Too many references: cannot splice");
1556 break;
1557 case WSAETIMEDOUT:
1558 sprintf(str,"Connection timed out");
1559 break;
1560 case WSAECONNREFUSED:
1561 sprintf(str,"Connection refused");
1562 break;
1563 case WSAELOOP:
1564 sprintf(str,"Too many symbolic links encountered");
1565 break;
1566 case WSAENAMETOOLONG:
1567 sprintf(str,"File name too long");
1568 break;
1569 case WSAEHOSTDOWN:
1570 sprintf(str,"Host is down");
1571 break;
1572 case WSAEHOSTUNREACH:
1573 sprintf(str,"No route to host");
1574 break;
1575 case WSAENOTEMPTY:
1576 sprintf(str,"Directory not empty");
1577 break;
1578 case WSAEUSERS:
1579 sprintf(str,"Too many users");
1580 break;
1581 case WSAEDQUOT:
1582 sprintf(str,"Quota exceeded");
1583 break;
1584 case WSAESTALE:
1585 sprintf(str,"Stale NFS file handle");
1586 break;
1587 case WSAEREMOTE:
1588 sprintf(str,"Object is remote");
1589 break;
1590 case WSAHOST_NOT_FOUND:
1591 sprintf(str,"Host not found");
1592 break;
1593 case WSATRY_AGAIN:
1594 sprintf(str,"Host not found, or SERVERFAIL");
1595 break;
1596 case WSANO_RECOVERY:
1597 sprintf(str,"Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1598 break;
1599 case WSANO_DATA:
1600 sprintf(str,"Valid name, no data record of requested type");
1601 break;
1602 default:
1603 sprintf(str,"Unknown error %d",code);
1604 }
1605 strcpy(msg, str);
1606}
1607#endif
1608
1609void tcpip_get_error( char *str, int code )
1610{
1611 DISABLE_AST
1612#ifndef WIN32
1613 if(code){}
1614 if((errno == ENOENT) && (h_errno == HOST_NOT_FOUND))
1615 strcpy(str,"Host not found");
1616 else
1617 strcpy(str, strerror(errno));
1618#else
1619 my_strerror(code, str);
1620#endif
1621 ENABLE_AST
1622}
Note: See TracBrowser for help on using the repository browser.