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

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