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

Last change on this file since 12408 was 11121, checked in by tbretz, 13 years ago
Updated from v19r21 to v19r22
File size: 32.3 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(s) close(s)
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 Net_conns[conn_id].write_timedout = 0;
993 return(1);
994}
995
996int tcpip_open_server( int conn_id, char *task, int *port )
997{
998 /* Create connection: create and initialize socket stuff,
999 * find a free port on this node.
1000 */
1001 struct sockaddr_in sockname;
1002 int path, val, ret_code, ret;
1003
1004 dim_tcpip_init(0);
1005 if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
1006 {
1007 return(0);
1008 }
1009
1010 val = 1;
1011 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1012 (char*)&val, sizeof(val))) == -1 )
1013
1014 {
1015#ifdef DEBUG
1016 printf("Couln't set TCP_NODELAY\n");
1017#endif
1018 closesock(path);
1019 return(0);
1020 }
1021
1022 val = Write_buffer_size;
1023 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1024 (void *)&val, sizeof(val))) == -1 )
1025 {
1026#ifdef DEBUG
1027 printf("Couln't set SO_SNDBUF\n");
1028#endif
1029 closesock(path);
1030 return(0);
1031 }
1032/*
1033 sval1 = sizeof(val1);
1034 if ((ret_code = getsockopt(path, SOL_SOCKET, SO_SNDBUF,
1035 (void *)&val1, &sval1)) == -1 )
1036 {
1037#ifdef DEBUG
1038 printf("Couln't set SO_SNDBUF\n");
1039#endif
1040 closesock(path);
1041 return(0);
1042 }
1043printf("Set size to %d, got size %d\n", val, val1);
1044*/
1045 val = Read_buffer_size;
1046 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1047 (void *)&val, sizeof(val))) == -1 )
1048 {
1049#ifdef DEBUG
1050 printf("Couln't set SO_RCVBUF\n");
1051#endif
1052 closesock(path);
1053 return(0);
1054 }
1055
1056 if( *port == SEEK_PORT )
1057 { /* Search a free one. */
1058 *port = START_PORT_RANGE - 1;
1059 do
1060 {
1061 (*port)++;
1062 sockname.sin_family = AF_INET;
1063 sockname.sin_addr.s_addr = INADDR_ANY;
1064 sockname.sin_port = htons((ushort) *port);
1065 if( *port > STOP_PORT_RANGE ) {
1066 errno = EADDRNOTAVAIL; /* fake an error code */
1067 closesock(path);
1068#ifdef WIN32
1069 WSASetLastError(errno);
1070#endif
1071 return(0);
1072 }
1073 ret = bind(path, (struct sockaddr*)&sockname, sizeof(sockname));
1074/*
1075printf("Trying port %d, ret = %d\n", *port, ret);
1076*/
1077 } while( ret == -1 );
1078/*
1079 } while( bind(path, (struct sockaddr*)&sockname, sizeof(sockname)) == -1 );
1080*/
1081 } else {
1082#ifndef WIN32
1083 val = 1;
1084 if( setsockopt(path, SOL_SOCKET, SO_REUSEADDR, (char*)&val,
1085 sizeof(val)) == -1 )
1086 {
1087#ifdef DEBUG
1088 printf("Couln't set SO_REUSEADDR\n");
1089#endif
1090 closesock(path);
1091 return(0);
1092 }
1093#endif
1094 sockname.sin_family = AF_INET;
1095 sockname.sin_addr.s_addr = INADDR_ANY;
1096 sockname.sin_port = htons((ushort) *port);
1097 if( (ret = bind(path, (struct sockaddr*) &sockname, sizeof(sockname))) == -1 )
1098 {
1099 closesock(path);
1100 return(0);
1101 }
1102 }
1103
1104 if( (ret = listen(path, SOMAXCONN)) == -1 )
1105 {
1106 closesock(path);
1107 return(0);
1108 }
1109
1110 strcpy( Net_conns[conn_id].node, "MYNODE" );
1111 strcpy( Net_conns[conn_id].task, task );
1112 Net_conns[conn_id].channel = path;
1113 Net_conns[conn_id].port = *port;
1114 Net_conns[conn_id].last_used = time(NULL);
1115 Net_conns[conn_id].reading = -1;
1116 Net_conns[conn_id].timr_ent = NULL;
1117 Net_conns[conn_id].write_timedout = 0;
1118 return(1);
1119}
1120
1121
1122int tcpip_start_listen( int conn_id, void (*ast_routine)() )
1123{
1124 /* Install signal handler stuff on the socket, and record
1125 * some necessary information: we are NOT reading, thus
1126 * no size.
1127 */
1128
1129 Net_conns[conn_id].read_rout = ast_routine;
1130 Net_conns[conn_id].size = -1;
1131 if(Net_conns[conn_id].reading == -1)
1132 {
1133 if(enable_sig( conn_id ) == -1)
1134 {
1135#ifdef DEBUG
1136 printf("START_LISTEN - enable_sig returned -1\n");
1137#endif
1138 return(0);
1139 }
1140 }
1141 Net_conns[conn_id].reading = FALSE;
1142 return(1);
1143}
1144
1145
1146int tcpip_open_connection( int conn_id, int path )
1147{
1148 /* Fill in/clear some fields, the node and task field
1149 * get filled in later by a special packet.
1150 */
1151 int val, ret_code;
1152
1153
1154 val = 1;
1155 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1156 (char*)&val, sizeof(val))) == -1 )
1157 {
1158#ifdef DEBUG
1159 printf("Couln't set TCP_NODELAY\n");
1160#endif
1161 closesock(path);
1162 return(0);
1163 }
1164 val = Write_buffer_size;
1165 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1166 (char*)&val, sizeof(val))) == -1 )
1167 {
1168#ifdef DEBUG
1169 printf("Couln't set SO_SNDBUF\n");
1170#endif
1171 closesock(path);
1172 return(0);
1173 }
1174
1175 val = Read_buffer_size;
1176 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1177 (char*)&val, sizeof(val))) == -1 )
1178 {
1179#ifdef DEBUG
1180 printf("Couln't set SO_RCVBUF\n");
1181#endif
1182 closesock(path);
1183 return(0);
1184 }
1185
1186 Net_conns[conn_id].channel = path;
1187 Net_conns[conn_id].node[0] = 0;
1188 Net_conns[conn_id].task[0] = 0;
1189 Net_conns[conn_id].port = 0;
1190 Net_conns[conn_id].reading = -1;
1191 Net_conns[conn_id].timr_ent = NULL;
1192 Net_conns[conn_id].write_timedout = 0;
1193 return(1);
1194}
1195
1196
1197void tcpip_get_node_task( int conn_id, char *node, char *task )
1198{
1199 strcpy( node, Net_conns[conn_id].node );
1200 strcpy( task, Net_conns[conn_id].task );
1201}
1202
1203int tcpip_write( int conn_id, char *buffer, int size )
1204{
1205 /* Do a (synchronous) write to conn_id.
1206 */
1207 int wrote;
1208
1209 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1210 if( wrote == -1 ) {
1211/*
1212 Net_conns[conn_id].read_rout( conn_id, -1, 0 );
1213*/
1214 return(0);
1215 }
1216 return(wrote);
1217}
1218
1219int set_non_blocking(int channel)
1220{
1221 int ret, flags = 1;
1222 ret = ioctl(channel, FIONBIO, &flags );
1223 if(ret == -1)
1224 {
1225#ifdef DEBUG
1226 printf("ioctl non block returned -1\n");
1227#endif
1228 return(ret);
1229 }
1230 return(1);
1231}
1232
1233int set_blocking(int channel)
1234{
1235 int ret, flags = 0;
1236 ret = ioctl(channel, FIONBIO, &flags );
1237 if(ret == -1)
1238 {
1239#ifdef DEBUG
1240 printf("ioctl block returned -1\n");
1241#endif
1242 return(ret);
1243 }
1244 return(1);
1245}
1246
1247int tcpip_write_nowait( int conn_id, char *buffer, int size )
1248{
1249 /* Do a (asynchronous) write to conn_id.
1250 */
1251 int wrote, ret, selret;
1252
1253 struct timeval timeout;
1254 fd_set wfds;
1255 int tcpip_would_block();
1256
1257 set_non_blocking(Net_conns[conn_id].channel);
1258 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1259#ifndef WIN32
1260 ret = errno;
1261#else
1262 ret = WSAGetLastError();
1263#endif
1264 set_blocking(Net_conns[conn_id].channel);
1265 if(wrote == -1)
1266 {
1267 if(tcpip_would_block(ret))
1268 {
1269 timeout.tv_sec = Write_timeout;
1270 timeout.tv_usec = 0;
1271 FD_ZERO(&wfds);
1272 FD_SET( Net_conns[conn_id].channel, &wfds);
1273 selret = select(FD_SETSIZE, NULL, &wfds, NULL, &timeout);
1274 if(selret > 0)
1275 {
1276 wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
1277 if( wrote == -1 )
1278 {
1279 return(0);
1280 }
1281 }
1282 }
1283 else
1284 {
1285 return(0);
1286 }
1287 }
1288 if(wrote == -1)
1289 {
1290 Net_conns[conn_id].write_timedout = 1;
1291 }
1292 return(wrote);
1293}
1294
1295int tcpip_close( int conn_id )
1296{
1297 int channel;
1298 /* Clear all traces of the connection conn_id.
1299 */
1300 if(Net_conns[conn_id].timr_ent)
1301 {
1302 dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
1303 Net_conns[conn_id].timr_ent = NULL;
1304 }
1305 channel = Net_conns[conn_id].channel;
1306 Net_conns[conn_id].channel = 0;
1307 Net_conns[conn_id].port = 0;
1308 Net_conns[conn_id].node[0] = 0;
1309 Net_conns[conn_id].task[0] = 0;
1310 if(channel)
1311 {
1312 if(Net_conns[conn_id].write_timedout)
1313 {
1314 Net_conns[conn_id].write_timedout = 0;
1315#if defined(__linux__) && !defined (darwin)
1316 shutdown(channel, 2);
1317#endif
1318 }
1319 closesock(channel);
1320 }
1321 return(1);
1322}
1323
1324
1325int tcpip_failure( int code )
1326{
1327 return(!code);
1328}
1329
1330int tcpip_would_block( int code )
1331{
1332 if(code == EWOULDBLOCK)
1333 return(1);
1334 return(0);
1335}
1336
1337void tcpip_report_error( int code )
1338{
1339#ifndef WIN32
1340 if(code){}
1341 perror("tcpip");
1342#else
1343 int my_perror();
1344
1345 my_perror("tcpip", code);
1346#endif
1347}
1348
1349#ifdef WIN32
1350int my_perror(char *str, int error)
1351{
1352int code;
1353
1354 if(error <= 0)
1355 code = WSAGetLastError();
1356 else
1357 code = error;
1358 printf("new - %s\n",strerror(code));
1359 printf("%s: ",str);
1360 switch(code)
1361 {
1362 case WSAEWOULDBLOCK:
1363 printf("Operation would block");
1364 break;
1365 case WSAEINPROGRESS:
1366 printf("Operation now in progress");
1367 break;
1368 case WSAEALREADY:
1369 printf("Operation already in progress");
1370 break;
1371 case WSAENOTSOCK:
1372 printf("Socket operation on non-socket");
1373 break;
1374 case WSAEDESTADDRREQ:
1375 printf("Destination address required");
1376 break;
1377 case WSAEMSGSIZE:
1378 printf("Message too long");
1379 break;
1380 case WSAEPROTOTYPE:
1381 printf("Protocol wrong type for socket");
1382 break;
1383 case WSAENOPROTOOPT:
1384 printf("Protocol not available");
1385 break;
1386 case WSAEPROTONOSUPPORT:
1387 printf("Protocol not supported");
1388 break;
1389 case WSAESOCKTNOSUPPORT:
1390 printf("Socket type not supported");
1391 break;
1392 case WSAEOPNOTSUPP:
1393 printf("Operation not supported on transport endpoint");
1394 break;
1395 case WSAEPFNOSUPPORT:
1396 printf("Protocol family not supported");
1397 break;
1398 case WSAEAFNOSUPPORT:
1399 printf("Address family not supported by protocol");
1400 break;
1401 case WSAEADDRINUSE:
1402 printf("Address already in use");
1403 break;
1404 case WSAEADDRNOTAVAIL:
1405 printf("Cannot assign requested address");
1406 break;
1407 case WSAENETDOWN:
1408 printf("Network is down");
1409 break;
1410 case WSAENETUNREACH:
1411 printf("Network is unreachable");
1412 break;
1413 case WSAENETRESET:
1414 printf("Network dropped connection because of reset");
1415 break;
1416 case WSAECONNABORTED:
1417 printf("Software caused connection abort");
1418 break;
1419 case WSAECONNRESET:
1420 printf("Connection reset by peer");
1421 break;
1422 case WSAENOBUFS:
1423 printf("No buffer space available");
1424 break;
1425 case WSAEISCONN:
1426 printf("Transport endpoint is already connected");
1427 break;
1428 case WSAENOTCONN:
1429 printf("Transport endpoint is not connected");
1430 break;
1431 case WSAESHUTDOWN:
1432 printf("Cannot send after transport endpoint shutdown");
1433 break;
1434 case WSAETOOMANYREFS:
1435 printf("Too many references: cannot splice");
1436 break;
1437 case WSAETIMEDOUT:
1438 printf("Connection timed out");
1439 break;
1440 case WSAECONNREFUSED:
1441 printf("Connection refused");
1442 break;
1443 case WSAELOOP:
1444 printf("Too many symbolic links encountered");
1445 break;
1446 case WSAENAMETOOLONG:
1447 printf("File name too long");
1448 break;
1449 case WSAEHOSTDOWN:
1450 printf("Host is down");
1451 break;
1452 case WSAEHOSTUNREACH:
1453 printf("No route to host");
1454 break;
1455 case WSAENOTEMPTY:
1456 printf("Directory not empty");
1457 break;
1458 case WSAEUSERS:
1459 printf("Too many users");
1460 break;
1461 case WSAEDQUOT:
1462 printf("Quota exceeded");
1463 break;
1464 case WSAESTALE:
1465 printf("Stale NFS file handle");
1466 break;
1467 case WSAEREMOTE:
1468 printf("Object is remote");
1469 break;
1470 case WSAHOST_NOT_FOUND:
1471 printf("Host not found");
1472 break;
1473 case WSATRY_AGAIN:
1474 printf("Host not found, or SERVERFAIL");
1475 break;
1476 case WSANO_RECOVERY:
1477 printf("Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1478 break;
1479 case WSANO_DATA:
1480 printf("Valid name, no data record of requested type");
1481 break;
1482 default:
1483 printf("Unknown error %d",code);
1484 }
1485 printf("\n");
1486 return(1);
1487}
1488
1489void my_strerror(int error, char *msg)
1490{
1491int code;
1492char str[128];
1493
1494 if(error <= 0)
1495 code = WSAGetLastError();
1496 else
1497 code = error;
1498 switch(code)
1499 {
1500 case WSAEWOULDBLOCK:
1501 sprintf(str,"Operation would block");
1502 break;
1503 case WSAEINPROGRESS:
1504 sprintf(str,"Operation now in progress");
1505 break;
1506 case WSAEALREADY:
1507 sprintf(str,"Operation already in progress");
1508 break;
1509 case WSAENOTSOCK:
1510 sprintf(str,"Socket operation on non-socket");
1511 break;
1512 case WSAEDESTADDRREQ:
1513 sprintf(str,"Destination address required");
1514 break;
1515 case WSAEMSGSIZE:
1516 sprintf(str,"Message too long");
1517 break;
1518 case WSAEPROTOTYPE:
1519 sprintf(str,"Protocol wrong type for socket");
1520 break;
1521 case WSAENOPROTOOPT:
1522 sprintf(str,"Protocol not available");
1523 break;
1524 case WSAEPROTONOSUPPORT:
1525 sprintf(str,"Protocol not supported");
1526 break;
1527 case WSAESOCKTNOSUPPORT:
1528 sprintf(str,"Socket type not supported");
1529 break;
1530 case WSAEOPNOTSUPP:
1531 sprintf(str,"Operation not supported on transport endpoint");
1532 break;
1533 case WSAEPFNOSUPPORT:
1534 sprintf(str,"Protocol family not supported");
1535 break;
1536 case WSAEAFNOSUPPORT:
1537 sprintf(str,"Address family not supported by protocol");
1538 break;
1539 case WSAEADDRINUSE:
1540 sprintf(str,"Address already in use");
1541 break;
1542 case WSAEADDRNOTAVAIL:
1543 sprintf(str,"Cannot assign requested address");
1544 break;
1545 case WSAENETDOWN:
1546 sprintf(str,"Network is down");
1547 break;
1548 case WSAENETUNREACH:
1549 sprintf(str,"Network is unreachable");
1550 break;
1551 case WSAENETRESET:
1552 sprintf(str,"Network dropped connection because of reset");
1553 break;
1554 case WSAECONNABORTED:
1555 sprintf(str,"Software caused connection abort");
1556 break;
1557 case WSAECONNRESET:
1558 sprintf(str,"Connection reset by peer");
1559 break;
1560 case WSAENOBUFS:
1561 sprintf(str,"No buffer space available");
1562 break;
1563 case WSAEISCONN:
1564 sprintf(str,"Transport endpoint is already connected");
1565 break;
1566 case WSAENOTCONN:
1567 sprintf(str,"Transport endpoint is not connected");
1568 break;
1569 case WSAESHUTDOWN:
1570 sprintf(str,"Cannot send after transport endpoint shutdown");
1571 break;
1572 case WSAETOOMANYREFS:
1573 sprintf(str,"Too many references: cannot splice");
1574 break;
1575 case WSAETIMEDOUT:
1576 sprintf(str,"Connection timed out");
1577 break;
1578 case WSAECONNREFUSED:
1579 sprintf(str,"Connection refused");
1580 break;
1581 case WSAELOOP:
1582 sprintf(str,"Too many symbolic links encountered");
1583 break;
1584 case WSAENAMETOOLONG:
1585 sprintf(str,"File name too long");
1586 break;
1587 case WSAEHOSTDOWN:
1588 sprintf(str,"Host is down");
1589 break;
1590 case WSAEHOSTUNREACH:
1591 sprintf(str,"No route to host");
1592 break;
1593 case WSAENOTEMPTY:
1594 sprintf(str,"Directory not empty");
1595 break;
1596 case WSAEUSERS:
1597 sprintf(str,"Too many users");
1598 break;
1599 case WSAEDQUOT:
1600 sprintf(str,"Quota exceeded");
1601 break;
1602 case WSAESTALE:
1603 sprintf(str,"Stale NFS file handle");
1604 break;
1605 case WSAEREMOTE:
1606 sprintf(str,"Object is remote");
1607 break;
1608 case WSAHOST_NOT_FOUND:
1609 sprintf(str,"Host not found");
1610 break;
1611 case WSATRY_AGAIN:
1612 sprintf(str,"Host not found, or SERVERFAIL");
1613 break;
1614 case WSANO_RECOVERY:
1615 sprintf(str,"Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1616 break;
1617 case WSANO_DATA:
1618 sprintf(str,"Valid name, no data record of requested type");
1619 break;
1620 default:
1621 sprintf(str,"Unknown error %d",code);
1622 }
1623 strcpy(msg, str);
1624}
1625#endif
1626
1627void tcpip_get_error( char *str, int code )
1628{
1629 DISABLE_AST
1630#ifndef WIN32
1631 if(code){}
1632 if((errno == ENOENT) && (h_errno == HOST_NOT_FOUND))
1633 strcpy(str,"Host not found");
1634 else
1635 strcpy(str, strerror(errno));
1636#else
1637 my_strerror(code, str);
1638#endif
1639 ENABLE_AST
1640}
Note: See TracBrowser for help on using the repository browser.