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

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