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

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