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

Last change on this file since 20068 was 19184, checked in by tbretz, 6 years ago
Updated to v20r23
File size: 37.9 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 if (pfds){} /* to avoid a warning */
893 MY_FD_SET( DIM_IO_path[0], pfds );
894#ifdef __linux__
895 ret = poll(Pollfds, Pollfd_size, -1);
896#else
897 ret = select(FD_SETSIZE, &rfds, NULL, &efds, NULL);
898#endif
899 if(ret <= 0)
900 {
901 printf("poll/select returned %d, errno %d\n", ret, errno);
902 }
903 if(ret > 0)
904 {
905 if(MY_FD_ISSET(DIM_IO_path[0], pfds) )
906 {
907#ifndef WIN32
908 read(DIM_IO_path[0], &data, 4);
909 DIM_IO_Done = 0;
910#endif
911 MY_FD_CLR( (unsigned)DIM_IO_path[0], pfds );
912 }
913/*
914 {
915 DISABLE_AST
916*/
917 conn_id = 0;
918 while( (ret = fds_get_entry( &rfds, &conn_id )) > 0 )
919 {
920 if( Net_conns[conn_id].reading )
921 {
922 count = 0;
923 do
924 {
925 DISABLE_AST
926 if(Net_conns[conn_id].channel)
927 {
928 do_read( conn_id );
929 count = get_bytes_to_read(conn_id);
930 }
931 else
932 {
933 count = 0;
934 }
935 ENABLE_AST
936 }while(count > 0 );
937 }
938 else
939 {
940 DISABLE_AST
941 do_accept( conn_id );
942 ENABLE_AST
943 }
944 MY_FD_CLR( (unsigned)Net_conns[conn_id].channel, &rfds );
945 }
946/*
947 ENABLE_AST
948 }
949*/
950#ifndef WIN32
951 return;
952#endif
953 }
954 }
955}
956
957int tcpip_start_read( int conn_id, char *buffer, int size, void (*ast_routine)() )
958{
959 /* Install signal handler stuff on the socket, and record
960 * some necessary information: we are reading, and want size
961 * as size, and use buffer.
962 */
963
964 Net_conns[conn_id].read_rout = ast_routine;
965 Net_conns[conn_id].buffer = buffer;
966 Net_conns[conn_id].size = size;
967 if(Net_conns[conn_id].reading == -1)
968 {
969 if(enable_sig( conn_id ) == -1)
970 {
971#ifdef DEBUG
972 printf("START_READ - enable_sig returned -1\n");
973#endif
974 return(0);
975 }
976 }
977 Net_conns[conn_id].reading = TRUE;
978 return(1);
979}
980
981int check_node_addr( char *node, unsigned char *ipaddr)
982{
983unsigned char *ptr;
984int ret;
985
986 ptr = (unsigned char *)node+(int)strlen(node)+1;
987 ipaddr[0] = *ptr++;
988 ipaddr[1] = *ptr++;
989 ipaddr[2] = *ptr++;
990 ipaddr[3] = *ptr++;
991 if( (ipaddr[0] == 0xff) &&
992 (ipaddr[1] == 0xff) &&
993 (ipaddr[2] == 0xff) &&
994 (ipaddr[3] == 0xff) )
995 {
996 errno = ECONNREFUSED; /* fake an error code */
997#ifdef WIN32
998 WSASetLastError(errno);
999#endif
1000 return(0);
1001 }
1002 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
1003 {
1004#ifndef WIN32
1005 ret = h_errno;
1006#else
1007 ret = WSAGetLastError();
1008#endif
1009 if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
1010 return(0);
1011/*
1012 errno = ECONNREFUSED;
1013#ifdef WIN32
1014 WSASetLastError(errno);
1015#endif
1016 return(0);
1017*/
1018 }
1019 return(1);
1020}
1021
1022int tcpip_open_client( int conn_id, char *node, char *task, int port )
1023{
1024 /* Create connection: create and initialize socket stuff. Try
1025 * and make a connection with the server.
1026 */
1027 struct sockaddr_in sockname;
1028#ifndef VxWorks
1029 struct hostent *host = 0;
1030#else
1031 int host_addr;
1032#endif
1033 int path, val, ret_code, ret, retcon, selret;
1034 int a,b,c,d;
1035/* Fix for gcc 4.6 "dereferencing type-punned pointer will break strict-aliasing rules"?!*/
1036 unsigned char ipaddr_buff[4];
1037 unsigned char *ipaddr = ipaddr_buff;
1038 int host_number = 0;
1039 int tcpip_would_block();
1040 int set_non_blocking();
1041 int set_blocking();
1042
1043#ifdef __linux__
1044 struct pollfd pollitem;
1045#else
1046 struct timeval timeout;
1047 fd_set rfds, wfds, efds;
1048#endif
1049 int so_error = ETIMEDOUT;
1050 unsigned int so_error_len = sizeof(so_error);
1051
1052 dim_tcpip_init(0);
1053 if(isdigit(node[0]))
1054 {
1055 sscanf(node,"%d.%d.%d.%d",&a, &b, &c, &d);
1056 ipaddr[0] = (unsigned char)a;
1057 ipaddr[1] = (unsigned char)b;
1058 ipaddr[2] = (unsigned char)c;
1059 ipaddr[3] = (unsigned char)d;
1060 host_number = 1;
1061/*
1062#ifndef VxWorks
1063 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
1064 {
1065#ifndef WIN32
1066 ret = h_errno;
1067#else
1068 ret = WSAGetLastError();
1069#endif
1070// if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
1071// {
1072// if(!check_node_addr(node, ipaddr))
1073// return(0);
1074// }
1075 }
1076#endif
1077*/
1078 }
1079#ifndef VxWorks
1080 else if( (host = gethostbyname(node)) == (struct hostent *)0 )
1081 {
1082 if(!check_node_addr(node, ipaddr))
1083 return(0);
1084 host_number = 1;
1085/*
1086 ptr = (unsigned char *)node+(int)strlen(node)+1;
1087 ipaddr[0] = *ptr++;
1088 ipaddr[1] = *ptr++;
1089 ipaddr[2] = *ptr++;
1090 ipaddr[3] = *ptr++;
1091 host_number = 1;
1092 if( (ipaddr[0] == 0xff) &&
1093 (ipaddr[1] == 0xff) &&
1094 (ipaddr[2] == 0xff) &&
1095 (ipaddr[3] == 0xff) )
1096 {
1097 errno = ECONNREFUSED;
1098#ifdef WIN32
1099 WSASetLastError(errno);
1100#endif
1101 return(0);
1102 }
1103 if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
1104 {
1105 errno = ECONNREFUSED;
1106#ifdef WIN32
1107 WSASetLastError(errno);
1108#endif
1109 return(0);
1110 }
1111*/
1112 }
1113#else
1114 *(strchr(node,'.')) = '\0';
1115 host_addr = hostGetByName(node);
1116 printf("node %s addr: %x\n",node, host_addr);
1117#endif
1118
1119 if( (path = (int)socket(AF_INET, SOCK_STREAM, 0)) == -1 )
1120 {
1121 perror("socket");
1122 return(0);
1123 }
1124
1125 val = 1;
1126
1127 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1128 (char*)&val, sizeof(val))) == -1 )
1129 {
1130#ifdef DEBUG
1131 printf("Couln't set TCP_NODELAY\n");
1132#endif
1133 closesock(path);
1134 return(0);
1135 }
1136
1137 val = Write_buffer_size;
1138 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1139 (char*)&val, sizeof(val))) == -1 )
1140 {
1141#ifdef DEBUG
1142 printf("Couln't set SO_SNDBUF\n");
1143#endif
1144 closesock(path);
1145 return(0);
1146 }
1147
1148 val = Read_buffer_size;
1149 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1150 (char*)&val, sizeof(val))) == -1 )
1151 {
1152#ifdef DEBUG
1153 printf("Couln't set SO_RCVBUF\n");
1154#endif
1155 closesock(path);
1156 return(0);
1157 }
1158
1159#if defined(__linux__) && !defined (darwin)
1160 val = 2;
1161 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_SYNCNT,
1162 (char*)&val, sizeof(val))) == -1 )
1163 {
1164#ifdef DEBUG
1165 printf("Couln't set TCP_SYNCNT\n");
1166#endif
1167 }
1168#endif
1169
1170 sockname.sin_family = PF_INET;
1171#ifndef VxWorks
1172 if(host_number)
1173 sockname.sin_addr = *((struct in_addr *) ipaddr);
1174 else
1175 sockname.sin_addr = *((struct in_addr *) host->h_addr);
1176#else
1177 if(host_number)
1178 sockname.sin_addr = *((struct in_addr *) ipaddr);
1179 else
1180 sockname.sin_addr = *((struct in_addr *) &host_addr);
1181#endif
1182 sockname.sin_port = htons((ushort) port); /* port number to send to */
1183 /*
1184 while ((ret = connect(path, (struct sockaddr*)&sockname, sizeof(sockname))) == -1)
1185 {
1186 if (errno != EINTR)
1187 {
1188 closesock(path);
1189 return(0);
1190 }
1191 }
1192 */
1193 set_non_blocking(path);
1194 retcon = connect(path, (struct sockaddr*)&sockname, sizeof(sockname));
1195#ifndef WIN32
1196 ret = errno;
1197#else
1198 ret = WSAGetLastError();
1199#endif
1200 set_blocking(path);
1201 if (retcon == -1)
1202 {
1203 if (tcpip_would_block(ret))
1204 {
1205#ifdef __linux__
1206 pollitem.fd = path;
1207 pollitem.events = POLLIN | POLLOUT | POLLERR;
1208 pollitem.revents = 0;
1209 selret = poll(&pollitem, 1, CONNECT_TMOUT * 1000);
1210#else
1211 timeout.tv_sec = CONNECT_TMOUT;
1212 timeout.tv_usec = 0;
1213 FD_ZERO(&wfds);
1214 FD_SET(path, &wfds);
1215 FD_ZERO(&rfds);
1216 FD_SET(path, &rfds);
1217 FD_ZERO(&efds);
1218 FD_SET(path, &efds);
1219 selret = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
1220#endif
1221 if (selret > 0)
1222 {
1223 getsockopt(path, SOL_SOCKET, SO_ERROR, (void *)&so_error, &so_error_len);
1224 }
1225 }
1226 if (so_error != 0)
1227 {
1228#ifndef WIN32
1229 errno = so_error;
1230#else
1231 WSASetLastError(so_error);
1232#endif
1233 closesock(path);
1234 return(0);
1235 }
1236 }
1237 strcpy(Net_conns[conn_id].node, node);
1238 strcpy( Net_conns[conn_id].task, task );
1239 Net_conns[conn_id].channel = path;
1240 Net_conns[conn_id].port = port;
1241 Net_conns[conn_id].last_used = time(NULL);
1242 Net_conns[conn_id].reading = -1;
1243 Net_conns[conn_id].timr_ent = NULL;
1244 Net_conns[conn_id].write_timedout = 0;
1245 return(1);
1246}
1247
1248int tcpip_open_server( int conn_id, char *task, int *port )
1249{
1250 /* Create connection: create and initialize socket stuff,
1251 * find a free port on this node.
1252 */
1253 struct sockaddr_in sockname;
1254 int path, val, ret_code, ret;
1255
1256 dim_tcpip_init(0);
1257 if( (path = (int)socket(AF_INET, SOCK_STREAM, 0)) == -1 )
1258 {
1259 return(0);
1260 }
1261
1262 val = 1;
1263 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1264 (char*)&val, sizeof(val))) == -1 )
1265
1266 {
1267#ifdef DEBUG
1268 printf("Couln't set TCP_NODELAY\n");
1269#endif
1270 closesock(path);
1271 return(0);
1272 }
1273
1274 val = Write_buffer_size;
1275 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1276 (void *)&val, sizeof(val))) == -1 )
1277 {
1278#ifdef DEBUG
1279 printf("Couln't set SO_SNDBUF\n");
1280#endif
1281 closesock(path);
1282 return(0);
1283 }
1284/*
1285 sval1 = sizeof(val1);
1286 if ((ret_code = getsockopt(path, SOL_SOCKET, SO_SNDBUF,
1287 (void *)&val1, &sval1)) == -1 )
1288 {
1289#ifdef DEBUG
1290 printf("Couln't set SO_SNDBUF\n");
1291#endif
1292 closesock(path);
1293 return(0);
1294 }
1295printf("Set size to %d, got size %d\n", val, val1);
1296*/
1297 val = Read_buffer_size;
1298 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1299 (void *)&val, sizeof(val))) == -1 )
1300 {
1301#ifdef DEBUG
1302 printf("Couln't set SO_RCVBUF\n");
1303#endif
1304 closesock(path);
1305 return(0);
1306 }
1307
1308 if( *port == SEEK_PORT )
1309 { /* Search a free one. */
1310 *port = START_PORT_RANGE - 1;
1311 do
1312 {
1313 (*port)++;
1314 sockname.sin_family = AF_INET;
1315 sockname.sin_addr.s_addr = INADDR_ANY;
1316 sockname.sin_port = htons((ushort) *port);
1317 if( *port > STOP_PORT_RANGE ) {
1318 errno = EADDRNOTAVAIL; /* fake an error code */
1319 closesock(path);
1320#ifdef WIN32
1321 WSASetLastError(errno);
1322#endif
1323 return(0);
1324 }
1325 ret = bind(path, (struct sockaddr*)&sockname, sizeof(sockname));
1326/*
1327printf("Trying port %d, ret = %d\n", *port, ret);
1328*/
1329 } while( ret == -1 );
1330/*
1331 } while( bind(path, (struct sockaddr*)&sockname, sizeof(sockname)) == -1 );
1332*/
1333 } else {
1334#ifndef WIN32
1335 val = 1;
1336 if( setsockopt(path, SOL_SOCKET, SO_REUSEADDR, (char*)&val,
1337 sizeof(val)) == -1 )
1338 {
1339#ifdef DEBUG
1340 printf("Couln't set SO_REUSEADDR\n");
1341#endif
1342 closesock(path);
1343 return(0);
1344 }
1345#endif
1346 sockname.sin_family = AF_INET;
1347 sockname.sin_addr.s_addr = INADDR_ANY;
1348 sockname.sin_port = htons((ushort) *port);
1349 if( (ret = bind(path, (struct sockaddr*) &sockname, sizeof(sockname))) == -1 )
1350 {
1351 closesock(path);
1352 return(0);
1353 }
1354 }
1355
1356 if( (ret = listen(path, Listen_backlog)) == -1 )
1357 {
1358 closesock(path);
1359 return(0);
1360 }
1361
1362 strcpy( Net_conns[conn_id].node, "MYNODE" );
1363 strcpy( Net_conns[conn_id].task, task );
1364 Net_conns[conn_id].channel = path;
1365 Net_conns[conn_id].port = *port;
1366 Net_conns[conn_id].last_used = time(NULL);
1367 Net_conns[conn_id].reading = -1;
1368 Net_conns[conn_id].timr_ent = NULL;
1369 Net_conns[conn_id].write_timedout = 0;
1370 return(1);
1371}
1372
1373
1374int tcpip_start_listen( int conn_id, void (*ast_routine)() )
1375{
1376 /* Install signal handler stuff on the socket, and record
1377 * some necessary information: we are NOT reading, thus
1378 * no size.
1379 */
1380
1381 Net_conns[conn_id].read_rout = ast_routine;
1382 Net_conns[conn_id].size = -1;
1383 if(Net_conns[conn_id].reading == -1)
1384 {
1385 if(enable_sig( conn_id ) == -1)
1386 {
1387#ifdef DEBUG
1388 printf("START_LISTEN - enable_sig returned -1\n");
1389#endif
1390 return(0);
1391 }
1392 }
1393 Net_conns[conn_id].reading = FALSE;
1394 return(1);
1395}
1396
1397
1398int tcpip_open_connection( int conn_id, int path )
1399{
1400 /* Fill in/clear some fields, the node and task field
1401 * get filled in later by a special packet.
1402 */
1403 int val, ret_code;
1404
1405
1406 val = 1;
1407 if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY,
1408 (char*)&val, sizeof(val))) == -1 )
1409 {
1410#ifdef DEBUG
1411 printf("Couln't set TCP_NODELAY\n");
1412#endif
1413 closesock(path);
1414 return(0);
1415 }
1416 val = Write_buffer_size;
1417 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF,
1418 (char*)&val, sizeof(val))) == -1 )
1419 {
1420#ifdef DEBUG
1421 printf("Couln't set SO_SNDBUF\n");
1422#endif
1423 closesock(path);
1424 return(0);
1425 }
1426
1427 val = Read_buffer_size;
1428 if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF,
1429 (char*)&val, sizeof(val))) == -1 )
1430 {
1431#ifdef DEBUG
1432 printf("Couln't set SO_RCVBUF\n");
1433#endif
1434 closesock(path);
1435 return(0);
1436 }
1437
1438 Net_conns[conn_id].channel = path;
1439 Net_conns[conn_id].node[0] = 0;
1440 Net_conns[conn_id].task[0] = 0;
1441 Net_conns[conn_id].port = 0;
1442 Net_conns[conn_id].reading = -1;
1443 Net_conns[conn_id].timr_ent = NULL;
1444 Net_conns[conn_id].write_timedout = 0;
1445 return(1);
1446}
1447
1448
1449void tcpip_get_node_task( int conn_id, char *node, char *task )
1450{
1451 strcpy( node, Net_conns[conn_id].node );
1452 strcpy( task, Net_conns[conn_id].task );
1453}
1454
1455int tcpip_write( int conn_id, char *buffer, int size )
1456{
1457 /* Do a (synchronous) write to conn_id.
1458 */
1459 int wrote;
1460
1461 wrote = (int)writesock( Net_conns[conn_id].channel, buffer, (size_t)size, 0 );
1462 if( wrote == -1 ) {
1463/*
1464 Net_conns[conn_id].read_rout( conn_id, -1, 0 );
1465*/
1466 dna_report_error(conn_id, 0,
1467 "Writing (blocking) to", DIM_ERROR, DIMTCPWRRTY);
1468 return(0);
1469 }
1470 return(wrote);
1471}
1472
1473int set_non_blocking(int channel)
1474{
1475 int ret, flags = 1;
1476 ret = ioctl(channel, FIONBIO, &flags );
1477 if(ret == -1)
1478 {
1479#ifdef DEBUG
1480 printf("ioctl non block returned -1\n");
1481#endif
1482 return(ret);
1483 }
1484 return(1);
1485}
1486
1487int set_blocking(int channel)
1488{
1489 int ret, flags = 0;
1490 ret = ioctl(channel, FIONBIO, &flags );
1491 if(ret == -1)
1492 {
1493#ifdef DEBUG
1494 printf("ioctl block returned -1\n");
1495#endif
1496 return(ret);
1497 }
1498 return(1);
1499}
1500
1501int tcpip_write_nowait( int conn_id, char *buffer, int size )
1502{
1503 /* Do a (asynchronous) write to conn_id.
1504 */
1505 int wrote, ret, selret;
1506 int tcpip_would_block();
1507 int set_non_blocking();
1508 int set_blocking();
1509
1510#ifdef __linux__
1511 struct pollfd pollitem;
1512#else
1513 struct timeval timeout;
1514 fd_set wfds;
1515#endif
1516
1517 set_non_blocking(Net_conns[conn_id].channel);
1518/*
1519#ifdef __linux__
1520 tcpip_get_send_space(conn_id);
1521#endif
1522*/
1523 wrote = (int)writesock( Net_conns[conn_id].channel, buffer, (size_t)size, 0 );
1524#ifndef WIN32
1525 ret = errno;
1526#else
1527 ret = WSAGetLastError();
1528#endif
1529/*
1530 if((wrote == -1) && (!tcpip_would_block(ret)))
1531 {
1532 dna_report_error(conn_id, 0,
1533 "Writing (non-blocking) to", DIM_ERROR, DIMTCPWRRTY);
1534printf("Writing %d, ret = %d\n", size, ret);
1535 }
1536*/
1537 set_blocking(Net_conns[conn_id].channel);
1538 if(wrote == -1)
1539 {
1540 if(tcpip_would_block(ret))
1541 {
1542#ifdef __linux__
1543 pollitem.fd = Net_conns[conn_id].channel;
1544 pollitem.events = POLLOUT;
1545 pollitem.revents = 0;
1546 selret = poll(&pollitem, 1, Write_timeout*1000);
1547#else
1548 timeout.tv_sec = Write_timeout;
1549 timeout.tv_usec = 0;
1550 FD_ZERO(&wfds);
1551 FD_SET( Net_conns[conn_id].channel, &wfds);
1552 selret = select(FD_SETSIZE, NULL, &wfds, NULL, &timeout);
1553#endif
1554 if(selret > 0)
1555 {
1556 wrote = (int)writesock( Net_conns[conn_id].channel, buffer, (size_t)size, 0 );
1557 if( wrote == -1 )
1558 {
1559 dna_report_error(conn_id, 0,
1560 "Writing to", DIM_ERROR, DIMTCPWRRTY);
1561 return(0);
1562 }
1563 }
1564 }
1565 else
1566 {
1567 dna_report_error(conn_id, 0,
1568 "Writing (non-blocking) to", DIM_ERROR, DIMTCPWRRTY);
1569 return(0);
1570 }
1571 }
1572 if(wrote == -1)
1573 {
1574 Net_conns[conn_id].write_timedout = 1;
1575 }
1576 return(wrote);
1577}
1578
1579int tcpip_close( int conn_id )
1580{
1581 int channel;
1582 /* Clear all traces of the connection conn_id.
1583 */
1584 if(Net_conns[conn_id].timr_ent)
1585 {
1586 dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
1587 Net_conns[conn_id].timr_ent = NULL;
1588 }
1589 channel = Net_conns[conn_id].channel;
1590 Net_conns[conn_id].channel = 0;
1591 Net_conns[conn_id].port = 0;
1592 Net_conns[conn_id].node[0] = 0;
1593 Net_conns[conn_id].task[0] = 0;
1594 if(channel)
1595 {
1596 if(Net_conns[conn_id].write_timedout)
1597 {
1598 Net_conns[conn_id].write_timedout = 0;
1599//#if defined(__linux__) && !defined (darwin)
1600// shutdown(channel, 2);
1601//#endif
1602 }
1603#if defined(__linux__) && !defined (darwin)
1604 shutdown(channel, 2);
1605#endif
1606 closesock(channel);
1607 }
1608 return(1);
1609}
1610
1611
1612int tcpip_failure( int code )
1613{
1614 return(!code);
1615}
1616
1617int tcpip_would_block( int code )
1618{
1619 if(code == EWOULDBLOCK)
1620 return(1);
1621 else if (code == EINPROGRESS)
1622 return(1);
1623 return(0);
1624}
1625
1626void tcpip_report_error( int code )
1627{
1628#ifndef WIN32
1629 if(code){}
1630 perror("tcpip");
1631#else
1632 int my_perror();
1633
1634 my_perror("tcpip", code);
1635#endif
1636}
1637
1638#ifdef WIN32
1639int my_perror(char *str, int error)
1640{
1641int code;
1642
1643 if(error <= 0)
1644 code = WSAGetLastError();
1645 else
1646 code = error;
1647 printf("new - %s\n",strerror(code));
1648 printf("%s: ",str);
1649 switch(code)
1650 {
1651 case WSAEWOULDBLOCK:
1652 printf("Operation would block");
1653 break;
1654 case WSAEINPROGRESS:
1655 printf("Operation now in progress");
1656 break;
1657 case WSAEALREADY:
1658 printf("Operation already in progress");
1659 break;
1660 case WSAENOTSOCK:
1661 printf("Socket operation on non-socket");
1662 break;
1663 case WSAEDESTADDRREQ:
1664 printf("Destination address required");
1665 break;
1666 case WSAEMSGSIZE:
1667 printf("Message too long");
1668 break;
1669 case WSAEPROTOTYPE:
1670 printf("Protocol wrong type for socket");
1671 break;
1672 case WSAENOPROTOOPT:
1673 printf("Protocol not available");
1674 break;
1675 case WSAEPROTONOSUPPORT:
1676 printf("Protocol not supported");
1677 break;
1678 case WSAESOCKTNOSUPPORT:
1679 printf("Socket type not supported");
1680 break;
1681 case WSAEOPNOTSUPP:
1682 printf("Operation not supported on transport endpoint");
1683 break;
1684 case WSAEPFNOSUPPORT:
1685 printf("Protocol family not supported");
1686 break;
1687 case WSAEAFNOSUPPORT:
1688 printf("Address family not supported by protocol");
1689 break;
1690 case WSAEADDRINUSE:
1691 printf("Address already in use");
1692 break;
1693 case WSAEADDRNOTAVAIL:
1694 printf("Cannot assign requested address");
1695 break;
1696 case WSAENETDOWN:
1697 printf("Network is down");
1698 break;
1699 case WSAENETUNREACH:
1700 printf("Network is unreachable");
1701 break;
1702 case WSAENETRESET:
1703 printf("Network dropped connection because of reset");
1704 break;
1705 case WSAECONNABORTED:
1706 printf("Software caused connection abort");
1707 break;
1708 case WSAECONNRESET:
1709 printf("Connection reset by peer");
1710 break;
1711 case WSAENOBUFS:
1712 printf("No buffer space available");
1713 break;
1714 case WSAEISCONN:
1715 printf("Transport endpoint is already connected");
1716 break;
1717 case WSAENOTCONN:
1718 printf("Transport endpoint is not connected");
1719 break;
1720 case WSAESHUTDOWN:
1721 printf("Cannot send after transport endpoint shutdown");
1722 break;
1723 case WSAETOOMANYREFS:
1724 printf("Too many references: cannot splice");
1725 break;
1726 case WSAETIMEDOUT:
1727 printf("Connection timed out");
1728 break;
1729 case WSAECONNREFUSED:
1730 printf("Connection refused");
1731 break;
1732 case WSAELOOP:
1733 printf("Too many symbolic links encountered");
1734 break;
1735 case WSAENAMETOOLONG:
1736 printf("File name too long");
1737 break;
1738 case WSAEHOSTDOWN:
1739 printf("Host is down");
1740 break;
1741 case WSAEHOSTUNREACH:
1742 printf("No route to host");
1743 break;
1744 case WSAENOTEMPTY:
1745 printf("Directory not empty");
1746 break;
1747 case WSAEUSERS:
1748 printf("Too many users");
1749 break;
1750 case WSAEDQUOT:
1751 printf("Quota exceeded");
1752 break;
1753 case WSAESTALE:
1754 printf("Stale NFS file handle");
1755 break;
1756 case WSAEREMOTE:
1757 printf("Object is remote");
1758 break;
1759 case WSAHOST_NOT_FOUND:
1760 printf("Host not found");
1761 break;
1762 case WSATRY_AGAIN:
1763 printf("Host not found, or SERVERFAIL");
1764 break;
1765 case WSANO_RECOVERY:
1766 printf("Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1767 break;
1768 case WSANO_DATA:
1769 printf("Valid name, no data record of requested type");
1770 break;
1771 default:
1772 printf("Unknown error %d",code);
1773 }
1774 printf("\n");
1775 return(1);
1776}
1777
1778void my_strerror(int error, char *msg)
1779{
1780int code;
1781char str[128];
1782
1783 if(error <= 0)
1784 code = WSAGetLastError();
1785 else
1786 code = error;
1787 switch(code)
1788 {
1789 case WSAEWOULDBLOCK:
1790 sprintf(str,"Operation would block");
1791 break;
1792 case WSAEINPROGRESS:
1793 sprintf(str,"Operation now in progress");
1794 break;
1795 case WSAEALREADY:
1796 sprintf(str,"Operation already in progress");
1797 break;
1798 case WSAENOTSOCK:
1799 sprintf(str,"Socket operation on non-socket");
1800 break;
1801 case WSAEDESTADDRREQ:
1802 sprintf(str,"Destination address required");
1803 break;
1804 case WSAEMSGSIZE:
1805 sprintf(str,"Message too long");
1806 break;
1807 case WSAEPROTOTYPE:
1808 sprintf(str,"Protocol wrong type for socket");
1809 break;
1810 case WSAENOPROTOOPT:
1811 sprintf(str,"Protocol not available");
1812 break;
1813 case WSAEPROTONOSUPPORT:
1814 sprintf(str,"Protocol not supported");
1815 break;
1816 case WSAESOCKTNOSUPPORT:
1817 sprintf(str,"Socket type not supported");
1818 break;
1819 case WSAEOPNOTSUPP:
1820 sprintf(str,"Operation not supported on transport endpoint");
1821 break;
1822 case WSAEPFNOSUPPORT:
1823 sprintf(str,"Protocol family not supported");
1824 break;
1825 case WSAEAFNOSUPPORT:
1826 sprintf(str,"Address family not supported by protocol");
1827 break;
1828 case WSAEADDRINUSE:
1829 sprintf(str,"Address already in use");
1830 break;
1831 case WSAEADDRNOTAVAIL:
1832 sprintf(str,"Cannot assign requested address");
1833 break;
1834 case WSAENETDOWN:
1835 sprintf(str,"Network is down");
1836 break;
1837 case WSAENETUNREACH:
1838 sprintf(str,"Network is unreachable");
1839 break;
1840 case WSAENETRESET:
1841 sprintf(str,"Network dropped connection because of reset");
1842 break;
1843 case WSAECONNABORTED:
1844 sprintf(str,"Software caused connection abort");
1845 break;
1846 case WSAECONNRESET:
1847 sprintf(str,"Connection reset by peer");
1848 break;
1849 case WSAENOBUFS:
1850 sprintf(str,"No buffer space available");
1851 break;
1852 case WSAEISCONN:
1853 sprintf(str,"Transport endpoint is already connected");
1854 break;
1855 case WSAENOTCONN:
1856 sprintf(str,"Transport endpoint is not connected");
1857 break;
1858 case WSAESHUTDOWN:
1859 sprintf(str,"Cannot send after transport endpoint shutdown");
1860 break;
1861 case WSAETOOMANYREFS:
1862 sprintf(str,"Too many references: cannot splice");
1863 break;
1864 case WSAETIMEDOUT:
1865 sprintf(str,"Connection timed out");
1866 break;
1867 case WSAECONNREFUSED:
1868 sprintf(str,"Connection refused");
1869 break;
1870 case WSAELOOP:
1871 sprintf(str,"Too many symbolic links encountered");
1872 break;
1873 case WSAENAMETOOLONG:
1874 sprintf(str,"File name too long");
1875 break;
1876 case WSAEHOSTDOWN:
1877 sprintf(str,"Host is down");
1878 break;
1879 case WSAEHOSTUNREACH:
1880 sprintf(str,"No route to host");
1881 break;
1882 case WSAENOTEMPTY:
1883 sprintf(str,"Directory not empty");
1884 break;
1885 case WSAEUSERS:
1886 sprintf(str,"Too many users");
1887 break;
1888 case WSAEDQUOT:
1889 sprintf(str,"Quota exceeded");
1890 break;
1891 case WSAESTALE:
1892 sprintf(str,"Stale NFS file handle");
1893 break;
1894 case WSAEREMOTE:
1895 sprintf(str,"Object is remote");
1896 break;
1897 case WSAHOST_NOT_FOUND:
1898 sprintf(str,"Host not found");
1899 break;
1900 case WSATRY_AGAIN:
1901 sprintf(str,"Host not found, or SERVERFAIL");
1902 break;
1903 case WSANO_RECOVERY:
1904 sprintf(str,"Non recoverable errors, FORMERR, REFUSED, NOTIMP");
1905 break;
1906 case WSANO_DATA:
1907 sprintf(str,"Valid name, no data record of requested type");
1908 break;
1909 default:
1910 sprintf(str,"Unknown error %d",code);
1911 }
1912 strcpy(msg, str);
1913}
1914#endif
1915
1916void tcpip_get_error( char *str, int code )
1917{
1918 DISABLE_AST
1919#ifndef WIN32
1920 if(code){}
1921 if((errno == 0) && (h_errno == HOST_NOT_FOUND))
1922 strcpy(str,"Host not found");
1923 else
1924 strcpy(str, strerror(errno));
1925#else
1926 my_strerror(code, str);
1927#endif
1928 ENABLE_AST
1929}
Note: See TracBrowser for help on using the repository browser.