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

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