Browse code

core: io wait - remove log level string from debug message

Daniel-Constantin Mierla authored on 12/11/2021 09:15:07
Showing 1 changed files
... ...
@@ -371,7 +371,7 @@ inline static int io_watch_add(	io_wait_h* h,
371 371
 		LM_CRIT("maximum fd number exceeded: %d/%d\n", h->fd_no, h->max_fd_no);
372 372
 		goto error;
373 373
 	}
374
-	DBG("DBG: io_watch_add(%p, %d, %d, %p), fd_no=%d\n",
374
+	DBG("processing io_watch_add(%p, %d, %d, %p) - fd_no=%d\n",
375 375
 			h, fd, type, data, h->fd_no);
376 376
 	/*  hash sanity check */
377 377
 	e=get_fd_map(h, fd);
Browse code

core: use main term for fields and in comments

Daniel-Constantin Mierla authored on 02/11/2020 11:37:18
Showing 1 changed files
... ...
@@ -168,8 +168,8 @@ typedef struct io_wait_handler {
168 168
 	int dpoll_fd;
169 169
 #endif
170 170
 #ifdef HAVE_SELECT
171
-	fd_set master_rset; /* read set */
172
-	fd_set master_wset; /* write set */
171
+	fd_set main_rset; /* read set */
172
+	fd_set main_wset; /* write set */
173 173
 	int max_fd_select; /* maximum select used fd */
174 174
 #endif
175 175
 } io_wait_h;
... ...
@@ -400,9 +400,9 @@ inline static int io_watch_add(	io_wait_h* h,
400 400
 		case POLL_SELECT:
401 401
 			fd_array_setup(events);
402 402
 			if (likely(events & POLLIN))
403
-				FD_SET(fd, &h->master_rset);
403
+				FD_SET(fd, &h->main_rset);
404 404
 			if (unlikely(events & POLLOUT))
405
-				FD_SET(fd, &h->master_wset);
405
+				FD_SET(fd, &h->main_wset);
406 406
 			if (h->max_fd_select<fd) h->max_fd_select=fd;
407 407
 			break;
408 408
 #endif
... ...
@@ -619,9 +619,9 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
619 619
 #ifdef HAVE_SELECT
620 620
 		case POLL_SELECT:
621 621
 			if (likely(events & POLLIN))
622
-				FD_CLR(fd, &h->master_rset);
622
+				FD_CLR(fd, &h->main_rset);
623 623
 			if (unlikely(events & POLLOUT))
624
-				FD_CLR(fd, &h->master_wset);
624
+				FD_CLR(fd, &h->main_wset);
625 625
 			if (unlikely(h->max_fd_select && (h->max_fd_select==fd)))
626 626
 				/* we don't know the prev. max, so we just decrement it */
627 627
 				h->max_fd_select--;
... ...
@@ -810,13 +810,13 @@ inline static int io_watch_chg(io_wait_h* h, int fd, short events, int idx )
810 810
 		case POLL_SELECT:
811 811
 			fd_array_chg(events);
812 812
 			if (unlikely(del_events & POLLIN))
813
-				FD_CLR(fd, &h->master_rset);
813
+				FD_CLR(fd, &h->main_rset);
814 814
 			else if (unlikely(add_events & POLLIN))
815
-				FD_SET(fd, &h->master_rset);
815
+				FD_SET(fd, &h->main_rset);
816 816
 			if (likely(del_events & POLLOUT))
817
-				FD_CLR(fd, &h->master_wset);
817
+				FD_CLR(fd, &h->main_wset);
818 818
 			else if (likely(add_events & POLLOUT))
819
-				FD_SET(fd, &h->master_wset);
819
+				FD_SET(fd, &h->main_wset);
820 820
 			break;
821 821
 #endif
822 822
 #ifdef HAVE_SIGIO_RT
... ...
@@ -992,10 +992,10 @@ inline static int io_wait_loop_select(io_wait_h* h, int t, int repeat)
992 992
 	int r;
993 993
 	struct fd_map* fm;
994 994
 	int revents;
995
-	
995
+
996 996
 again:
997
-		sel_rset=h->master_rset;
998
-		sel_wset=h->master_wset;
997
+		sel_rset=h->main_rset;
998
+		sel_wset=h->main_wset;
999 999
 		timeout.tv_sec=t;
1000 1000
 		timeout.tv_usec=0;
1001 1001
 		ret=n=select(h->max_fd_select+1, &sel_rset, &sel_wset, 0, &timeout);
Browse code

core: io wait - unhash in case delete operation fails because of EBADF

- EBADF: epfd or fd is not a valid file descriptor

Daniel-Constantin Mierla authored on 07/07/2020 15:37:00
Showing 1 changed files
... ...
@@ -669,6 +669,13 @@ again_epoll:
669 669
 					if (errno==EAGAIN) goto again_epoll;
670 670
 					LM_ERR("removing fd %d from epoll list failed: %s [%d]\n",
671 671
 						fd, strerror(errno), errno);
672
+					if (unlikely(errno==EBADF)) {
673
+						LM_ERR("unhashing of invalid fd - %d (epfd %d)\n", fd,
674
+								h->epfd);
675
+						unhash_fd_map(e);
676
+						h->fd_no--;
677
+					}
678
+
672 679
 					goto error;
673 680
 				}
674 681
 #ifdef EPOLL_NO_CLOSE_BUG
Browse code

Revert "core: io wait - unhash in case delete operation fails because of EBADF"

This reverts commit 60119faef5282b135ef7c972d15e1017ca26815a.

Daniel-Constantin Mierla authored on 07/07/2020 15:36:22
Showing 1 changed files
... ...
@@ -669,12 +669,6 @@ again_epoll:
669 669
 					if (errno==EAGAIN) goto again_epoll;
670 670
 					LM_ERR("removing fd %d from epoll list failed: %s [%d]\n",
671 671
 						fd, strerror(errno), errno);
672
-					if (unlikely(errno==EBADF)) {
673
-						LM_ERR("unhashing of invalid fd - %d (epfd %d)\n", fd,
674
-								h->h->epfd);
675
-						unhash_fd_map(e);
676
-						h->fd_no--;
677
-					}
678 672
 					goto error;
679 673
 				}
680 674
 #ifdef EPOLL_NO_CLOSE_BUG
Browse code

core: io wait - unhash in case delete operation fails because of EBADF

- EBADF: epfd or fd is not a valid file descriptor

Daniel-Constantin Mierla authored on 07/07/2020 15:25:00
Showing 1 changed files
... ...
@@ -669,6 +669,12 @@ again_epoll:
669 669
 					if (errno==EAGAIN) goto again_epoll;
670 670
 					LM_ERR("removing fd %d from epoll list failed: %s [%d]\n",
671 671
 						fd, strerror(errno), errno);
672
+					if (unlikely(errno==EBADF)) {
673
+						LM_ERR("unhashing of invalid fd - %d (epfd %d)\n", fd,
674
+								h->h->epfd);
675
+						unhash_fd_map(e);
676
+						h->fd_no--;
677
+					}
672 678
 					goto error;
673 679
 				}
674 680
 #ifdef EPOLL_NO_CLOSE_BUG
Browse code

core: tcp - more details on error log messages

Daniel-Constantin Mierla authored on 03/07/2020 08:49:43
Showing 1 changed files
... ...
@@ -415,13 +415,13 @@ inline static int io_watch_add(	io_wait_h* h,
415 415
 			 */
416 416
 			/* set async & signal */
417 417
 			if (fcntl(fd, F_SETOWN, my_pid())==-1){
418
-				LM_ERR("fnctl: SETOWN failed: %s [%d]\n",
419
-					strerror(errno), errno);
418
+				LM_ERR("fnctl: SETOWN on fd %d failed: %s [%d]\n",
419
+					fd, strerror(errno), errno);
420 420
 				goto error;
421 421
 			}
422 422
 			if (fcntl(fd, F_SETSIG, h->signo)==-1){
423
-				LM_ERR("fnctl: SETSIG failed: %s [%d]\n",
424
-					strerror(errno), errno);
423
+				LM_ERR("fnctl: SETSIG on fd %d failed: %s [%d]\n",
424
+					fd, strerror(errno), errno);
425 425
 				goto error;
426 426
 			}
427 427
 			/* set both non-blocking and async */
... ...
@@ -455,7 +455,8 @@ again1:
455 455
 			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
456 456
 			if (unlikely(n==-1)){
457 457
 				if (errno==EAGAIN) goto again1;
458
-				LM_ERR("epoll_ctl failed: %s [%d]\n", strerror(errno), errno);
458
+				LM_ERR("epoll_ctl on fd %d failed: %s [%d]\n",
459
+						fd, strerror(errno), errno);
459 460
 				goto error;
460 461
 			}
461 462
 			break;
... ...
@@ -475,7 +476,8 @@ again2:
475 476
 			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
476 477
 			if (unlikely(n==-1)){
477 478
 				if (errno==EAGAIN) goto again2;
478
-				LM_ERR("epoll_ctl failed: %s [%d]\n", strerror(errno), errno);
479
+				LM_ERR("epoll_ctl on fd %d failed: %s [%d]\n",
480
+						fd, strerror(errno), errno);
479 481
 				goto error;
480 482
 			}
481 483
 			break;
... ...
@@ -505,8 +507,8 @@ again2:
505 507
 again_devpoll:
506 508
 			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
507 509
 				if (errno==EAGAIN) goto again_devpoll;
508
-				LM_ERR("/dev/poll write failed: %s [%d]\n",
509
-					strerror(errno), errno);
510
+				LM_ERR("/dev/poll write of fd %d failed: %s [%d]\n",
511
+					fd, strerror(errno), errno);
510 512
 				goto error;
511 513
 			}
512 514
 			break;
... ...
@@ -532,7 +534,8 @@ check_io_again:
532 534
 				(pf.revents & (e->events|POLLERR|POLLHUP)));
533 535
 		if (unlikely(e->type && (n==-1))){
534 536
 			if (errno==EINTR) goto check_io_again;
535
-			LM_ERR("check_io poll: %s [%d]\n", strerror(errno), errno);
537
+			LM_ERR("check_io poll on fd %d failed: %s [%d]\n",
538
+					fd, strerror(errno), errno);
536 539
 		}
537 540
 	}
538 541
 #endif
... ...
@@ -637,13 +640,13 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
637 640
 				/* reset ASYNC */
638 641
 				fd_flags=fcntl(fd, F_GETFL);
639 642
 				if (unlikely(fd_flags==-1)){
640
-					LM_ERR("fnctl: GETFL failed: %s [%d]\n",
641
-						strerror(errno), errno);
643
+					LM_ERR("fnctl: GETFL on fd %d failed: %s [%d]\n",
644
+						fd, strerror(errno), errno);
642 645
 					goto error;
643 646
 				}
644 647
 				if (unlikely(fcntl(fd, F_SETFL, fd_flags&(~O_ASYNC))==-1)){
645
-					LM_ERR("fnctl: SETFL failed: %s [%d]\n",
646
-						strerror(errno), errno);
648
+					LM_ERR("fnctl: SETFL on fd %d failed: %s [%d]\n",
649
+						fd, strerror(errno), errno);
647 650
 					goto error;
648 651
 				}
649 652
 			fix_fd_array; /* only on success */
... ...
@@ -664,8 +667,8 @@ again_epoll:
664 667
 				n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
665 668
 				if (unlikely(n==-1)){
666 669
 					if (errno==EAGAIN) goto again_epoll;
667
-					LM_ERR("removing fd from epoll list failed: %s [%d]\n",
668
-						strerror(errno), errno);
670
+					LM_ERR("removing fd %d from epoll list failed: %s [%d]\n",
671
+						fd, strerror(errno), errno);
669 672
 					goto error;
670 673
 				}
671 674
 #ifdef EPOLL_NO_CLOSE_BUG
... ...
@@ -704,8 +707,8 @@ again_epoll:
704 707
 again_devpoll:
705 708
 				if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
706 709
 					if (errno==EINTR) goto again_devpoll;
707
-					LM_ERR("removing fd from /dev/poll failed: %s [%d]\n",
708
-						strerror(errno), errno);
710
+					LM_ERR("removing fd %d from /dev/poll failed: %s [%d]\n",
711
+						fd, strerror(errno), errno);
709 712
 					goto error;
710 713
 				}
711 714
 				break;
... ...
@@ -831,8 +834,8 @@ again_epoll_lt:
831 834
 				n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
832 835
 				if (unlikely(n==-1)){
833 836
 					if (errno==EAGAIN) goto again_epoll_lt;
834
-					LM_ERR("modifying epoll events failed: %s [%d]\n",
835
-						strerror(errno), errno);
837
+					LM_ERR("modifying epoll events of fd %d failed: %s [%d]\n",
838
+						fd, strerror(errno), errno);
836 839
 					goto error;
837 840
 				}
838 841
 			break;
... ...
@@ -851,8 +854,8 @@ again_epoll_et:
851 854
 				n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
852 855
 				if (unlikely(n==-1)){
853 856
 					if (errno==EAGAIN) goto again_epoll_et;
854
-					LM_ERR("modifying epoll events failed: %s [%d]\n",
855
-						strerror(errno), errno);
857
+					LM_ERR("modifying epoll events of fd %d failed: %s [%d]\n",
858
+						fd, strerror(errno), errno);
856 859
 					goto error;
857 860
 				}
858 861
 			break;
... ...
@@ -887,8 +890,8 @@ again_epoll_et:
887 890
 again_devpoll1:
888 891
 				if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
889 892
 					if (errno==EINTR) goto again_devpoll1;
890
-					LM_ERR("removing fd from /dev/poll failed: %s [%d]\n",
891
-								strerror(errno), errno);
893
+					LM_ERR("removing fd %d from /dev/poll failed: %s [%d]\n",
894
+								fd, strerror(errno), errno);
892 895
 					goto error;
893 896
 				}
894 897
 again_devpoll2:
... ...
@@ -896,8 +899,8 @@ again_devpoll2:
896 899
 				pfd.revents=0;
897 900
 				if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
898 901
 					if (errno==EINTR) goto again_devpoll2;
899
-					LM_ERR("re-adding fd to /dev/poll failed: %s [%d]\n",
900
-								strerror(errno), errno);
902
+					LM_ERR("re-adding fd %d to /dev/poll failed: %s [%d]\n",
903
+								fd, strerror(errno), errno);
901 904
 					/* error re-adding the fd => mark it as removed/unhash */
902 905
 					unhash_fd_map(e);
903 906
 					goto error;
Browse code

core: io_wait.h - typedef fd_map_t, more details in log when is a fd conflict

Daniel-Constantin Mierla authored on 03/06/2020 06:55:57
Showing 1 changed files
... ...
@@ -109,12 +109,12 @@ typedef int fd_type;
109 109
 
110 110
 /* maps a fd to some other structure; used in almost all cases
111 111
  * except epoll and maybe kqueue or /dev/poll */
112
-struct fd_map{
112
+typedef struct fd_map {
113 113
 	int fd;               /* fd no */
114 114
 	fd_type type;         /* "data" type */
115 115
 	void* data;           /* pointer to the corresponding structure */
116 116
 	short events;         /* events we are interested int */
117
-};
117
+} fd_map_t;
118 118
 
119 119
 
120 120
 #ifdef HAVE_KQUEUE
... ...
@@ -132,7 +132,7 @@ struct fd_map{
132 132
 
133 133
 
134 134
 /* handler structure */
135
-struct io_wait_handler{
135
+typedef struct io_wait_handler {
136 136
 	enum poll_types poll_method;
137 137
 	int flags;
138 138
 	struct fd_map* fd_hash;
... ...
@@ -172,13 +172,12 @@ struct io_wait_handler{
172 172
 	fd_set master_wset; /* write set */
173 173
 	int max_fd_select; /* maximum select used fd */
174 174
 #endif
175
-};
176
-
177
-typedef struct io_wait_handler io_wait_h;
175
+} io_wait_h;
178 176
 
179 177
 
180 178
 /* get the corresponding fd_map structure pointer */
181 179
 #define get_fd_map(h, fd)		(&(h)->fd_hash[(fd)])
180
+
182 181
 /* remove a fd_map structure from the hash; the pointer must be returned
183 182
  * by get_fd_map or hash_fd_map*/
184 183
 #define unhash_fd_map(pfm)	\
... ...
@@ -321,7 +320,7 @@ inline static int io_watch_add(	io_wait_h* h,
321 320
 		h->fd_array[h->fd_no].events=(ev); /* useless for select */ \
322 321
 		h->fd_array[h->fd_no].revents=0;     /* useless for select */ \
323 322
 	}while(0)
324
-	
323
+
325 324
 #define set_fd_flags(f) \
326 325
 	do{ \
327 326
 			flags=fcntl(fd, F_GETFL); \
... ...
@@ -336,8 +335,7 @@ inline static int io_watch_add(	io_wait_h* h,
336 335
 				goto error; \
337 336
 			} \
338 337
 	}while(0)
339
-	
340
-	
338
+
341 339
 	struct fd_map* e;
342 340
 	int flags;
343 341
 #ifdef HAVE_EPOLL
... ...
@@ -353,7 +351,7 @@ inline static int io_watch_add(	io_wait_h* h,
353 351
 	int idx;
354 352
 	int check_io;
355 353
 	struct pollfd pf;
356
-	
354
+
357 355
 	check_io=0; /* set to 1 if we need to check for pre-existing queued
358 356
 				   io/data on the fd */
359 357
 	idx=-1;
... ...
@@ -378,13 +376,13 @@ inline static int io_watch_add(	io_wait_h* h,
378 376
 	/*  hash sanity check */
379 377
 	e=get_fd_map(h, fd);
380 378
 	if (unlikely(e && (e->type!=0 /*F_NONE*/))){
381
-		LM_ERR("trying to overwrite entry %d"
382
-			" watched for %x in the hash(%d, %d, %p) with (%d, %d, %p)\n",
383
-			fd, events, e->fd, e->type, e->data, fd, type, data);
379
+		LM_ERR("trying to overwrite entry %d watched for %x"
380
+			" in the hash %p (fd:%d, type:%d, data:%p) with (%d, %d, %p)\n",
381
+			fd, events, h, e->fd, e->type, e->data, fd, type, data);
384 382
 		e=0;
385 383
 		goto error;
386 384
 	}
387
-	
385
+
388 386
 	if (unlikely((e=hash_fd_map(h, fd, events, type, data))==0)){
389 387
 		LM_ERR("failed to hash the fd %d\n", fd);
390 388
 		goto error;
Browse code

core: cleanup, remove local_malloc/local_free #define in core

- remove the unused local_malloc and local_free #define in the core
- they were introduced in 2002 and not touched in the repository since this time
- they pointed to pkg_malloc and pkg_free

Henning Westerholt authored on 23/12/2018 21:50:43
Showing 1 changed files
... ...
@@ -33,9 +33,6 @@
33 33
  *                to int). 0 has a special not set/not init. meaning
34 34
  *                (a lot of sanity checks and the sigio_rt code are based on
35 35
  *                 this assumption)
36
- *     local_malloc (defaults to pkg_malloc)
37
- *     local_free   (defaults to pkg_free)
38
- *
39 36
  */
40 37
 
41 38
 #ifndef _io_wait_h
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1393 @@
1
+/*
2
+ * Copyright (C) 2005 iptelorg GmbH
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+/*!
17
+* \file
18
+* \brief Kamailio core :: tcp io wait common stuff used by tcp_main.c & tcp_read.c
19
+* \ingroup core
20
+* Module: \ref core
21
+* \author andrei
22
+*
23
+ * All the functions are inline because of speed reasons and because they are
24
+ * used only from 2 places.
25
+ *
26
+ * You also have to define:
27
+ *     int handle_io(struct fd_map* fm, short events, int idx) (see below)
28
+ *     (this could be trivially replaced by a callback pointer entry attached
29
+ *      to the io_wait handler if more flexibility rather then performance
30
+ *      is needed)
31
+ *      fd_type - define to some enum of you choice and define also
32
+ *                FD_TYPE_DEFINED (if you don't do it fd_type will be defined
33
+ *                to int). 0 has a special not set/not init. meaning
34
+ *                (a lot of sanity checks and the sigio_rt code are based on
35
+ *                 this assumption)
36
+ *     local_malloc (defaults to pkg_malloc)
37
+ *     local_free   (defaults to pkg_free)
38
+ *
39
+ */
40
+
41
+#ifndef _io_wait_h
42
+#define _io_wait_h
43
+
44
+#include <errno.h>
45
+#include <string.h>
46
+#ifdef HAVE_SIGIO_RT
47
+#define __USE_GNU /* or else F_SETSIG won't be included */
48
+#include <sys/types.h> /* recv */
49
+#include <sys/socket.h> /* recv */
50
+#include <signal.h> /* sigprocmask, sigwait a.s.o */
51
+#endif
52
+
53
+#define _GNU_SOURCE  /* for POLLRDHUP on linux */
54
+#include <poll.h>
55
+#include <fcntl.h>
56
+
57
+#ifdef HAVE_EPOLL
58
+#include <sys/epoll.h>
59
+#endif
60
+#ifdef HAVE_KQUEUE
61
+#include <sys/types.h> /* needed on freebsd */
62
+#include <sys/event.h>
63
+#include <sys/time.h>
64
+#endif
65
+#ifdef HAVE_DEVPOLL
66
+#include <sys/devpoll.h>
67
+#endif
68
+#ifdef HAVE_SELECT
69
+/* needed on openbsd for select*/
70
+#include <sys/time.h>
71
+#include <sys/types.h>
72
+#include <unistd.h>
73
+/* needed according to POSIX for select*/
74
+#include <sys/select.h>
75
+#endif
76
+
77
+#include "dprint.h"
78
+
79
+#include "poll_types.h" /* poll_types*/
80
+#ifdef HAVE_SIGIO_RT
81
+#include "pt.h" /* mypid() */
82
+#endif
83
+
84
+#include "compiler_opt.h"
85
+
86
+
87
+#ifdef HAVE_EPOLL
88
+/* fix defines for EPOLL */
89
+#if defined POLLRDHUP && ! defined EPOLLRDHUP
90
+#define EPOLLRDHUP POLLRDHUP  /* should work on all linuxes */
91
+#endif /* POLLRDHUP && EPOLLRDHUP */
92
+#endif /* HAVE_EPOLL */
93
+
94
+
95
+extern int _os_ver; /* os version number, needed to select bugs workarrounds */
96
+
97
+
98
+#if 0
99
+enum fd_types; /* this should be defined from the including file,
100
+				  see tcp_main.c for an example,
101
+				  0 has a special meaning: not used/empty*/
102
+#endif
103
+
104
+#ifndef FD_TYPE_DEFINED
105
+typedef int fd_type;
106
+#define FD_TYPE_DEFINED
107
+#endif
108
+
109
+#ifdef __SUNPRO_C
110
+#pragma weak handle_io
111
+#endif
112
+
113
+/* maps a fd to some other structure; used in almost all cases
114
+ * except epoll and maybe kqueue or /dev/poll */
115
+struct fd_map{
116
+	int fd;               /* fd no */
117
+	fd_type type;         /* "data" type */
118
+	void* data;           /* pointer to the corresponding structure */
119
+	short events;         /* events we are interested int */
120
+};
121
+
122
+
123
+#ifdef HAVE_KQUEUE
124
+#ifndef KQ_CHANGES_ARRAY_SIZE
125
+#define KQ_CHANGES_ARRAY_SIZE 256
126
+
127
+#ifdef __OS_netbsd
128
+#define KEV_UDATA_CAST (intptr_t)
129
+#else
130
+#define KEV_UDATA_CAST
131
+#endif
132
+
133
+#endif
134
+#endif
135
+
136
+
137
+/* handler structure */
138
+struct io_wait_handler{
139
+	enum poll_types poll_method;
140
+	int flags;
141
+	struct fd_map* fd_hash;
142
+	int fd_no; /*  current index used in fd_array and the passed size for
143
+				   ep_array (for kq_array at least
144
+				    max(twice the size, kq_changes_size) should be
145
+				   be passed). */
146
+	int max_fd_no; /* maximum fd no, is also the size of fd_array,
147
+						       fd_hash  and ep_array*/
148
+	/* common stuff for POLL, SIGIO_RT and SELECT
149
+	 * since poll support is always compiled => this will always be compiled */
150
+	struct pollfd* fd_array; /* used also by devpoll as devpoll array */
151
+	int crt_fd_array_idx; /*  crt idx for which handle_io is called
152
+							 (updated also by del -> internal optimization) */
153
+	/* end of common stuff */
154
+#ifdef HAVE_EPOLL
155
+	int epfd; /* epoll ctrl fd */
156
+	struct epoll_event* ep_array;
157
+#endif
158
+#ifdef HAVE_SIGIO_RT
159
+	sigset_t sset; /* signal mask for sigio & sigrtmin */
160
+	int signo;     /* real time signal used */
161
+#endif
162
+#ifdef HAVE_KQUEUE
163
+	int kq_fd;
164
+	struct kevent* kq_array;   /* used for the eventlist*/
165
+	struct kevent* kq_changes; /* used for the changelist */
166
+	size_t kq_nchanges;
167
+	size_t kq_array_size;   /* array size */
168
+	size_t kq_changes_size; /* size of the changes array */
169
+#endif
170
+#ifdef HAVE_DEVPOLL
171
+	int dpoll_fd;
172
+#endif
173
+#ifdef HAVE_SELECT
174
+	fd_set master_rset; /* read set */
175
+	fd_set master_wset; /* write set */
176
+	int max_fd_select; /* maximum select used fd */
177
+#endif
178
+};
179
+
180
+typedef struct io_wait_handler io_wait_h;
181
+
182
+
183
+/* get the corresponding fd_map structure pointer */
184
+#define get_fd_map(h, fd)		(&(h)->fd_hash[(fd)])
185
+/* remove a fd_map structure from the hash; the pointer must be returned
186
+ * by get_fd_map or hash_fd_map*/
187
+#define unhash_fd_map(pfm)	\
188
+	do{ \
189
+		(pfm)->type=0 /*F_NONE */; \
190
+		(pfm)->fd=-1; \
191
+	}while(0)
192
+
193
+/* add a fd_map structure to the fd hash */
194
+static inline struct fd_map* hash_fd_map(	io_wait_h* h,
195
+											int fd,
196
+											short events,
197
+											fd_type type,
198
+											void* data)
199
+{
200
+	h->fd_hash[fd].fd=fd;
201
+	h->fd_hash[fd].events=events;
202
+	h->fd_hash[fd].type=type;
203
+	h->fd_hash[fd].data=data;
204
+	return &h->fd_hash[fd];
205
+}
206
+
207
+
208
+
209
+#ifdef HANDLE_IO_INLINE
210
+/* generic handle io routine, this must be defined in the including file
211
+ * (faster then registering a callback pointer)
212
+ *
213
+ * params:  fm     - pointer to a fd hash entry
214
+ *          events - combinations of POLLIN, POLLOUT, POLLERR & POLLHUP
215
+ *          idx    - index in the fd_array (or -1 if not known)
216
+ * return: -1 on error
217
+ *          0 on EAGAIN or when by some other way it is known that no more
218
+ *            io events are queued on the fd (the receive buffer is empty).
219
+ *            Usefull to detect when there are no more io events queued for
220
+ *            sigio_rt, epoll_et, kqueue.
221
+ *         >0 on successfull read from the fd (when there might be more io
222
+ *            queued -- the receive buffer might still be non-empty)
223
+ */
224
+inline static int handle_io(struct fd_map* fm, short events, int idx);
225
+#else
226
+int handle_io(struct fd_map* fm, short events, int idx);
227
+#endif
228
+
229
+
230
+
231
+#ifdef HAVE_KQUEUE
232
+/*
233
+ * kqueue specific function: register a change
234
+ * (adds a change to the kevent change array, and if full flushes it first)
235
+ *
236
+ * TODO: check if the event already exists in the change list or if it's
237
+ *       complementary to an event in the list (e.g. EVFILT_WRITE, EV_DELETE
238
+ *       and EVFILT_WRITE, EV_ADD for the same fd).
239
+ * returns: -1 on error, 0 on success
240
+ */
241
+static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag,
242
+								void* data)
243
+{
244
+	int n;
245
+	int r;
246
+	struct timespec tspec;
247
+
248
+	if (h->kq_nchanges>=h->kq_changes_size){
249
+		/* changes array full ! */
250
+		LM_WARN("kqueue changes array full trying to flush...\n");
251
+		tspec.tv_sec=0;
252
+		tspec.tv_nsec=0;
253
+again:
254
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec);
255
+		if (unlikely(n == -1)){
256
+			if (unlikely(errno == EINTR)) goto again;
257
+			else {
258
+				/* for a detailed explanation of what follows see
259
+				   io_wait_loop_kqueue EV_ERROR case */
260
+				if (unlikely(!(errno == EBADF || errno == ENOENT)))
261
+					BUG("kq_ev_change: kevent flush changes failed"
262
+							" (unexpected error): %s [%d]\n",
263
+							strerror(errno), errno);
264
+					/* ignore error even if it's not a EBADF/ENOENT */
265
+				/* one of the file descriptors is bad, probably already
266
+				   closed => try to apply changes one-by-one */
267
+				for (r = 0; r < h->kq_nchanges; r++) {
268
+retry2:
269
+					n = kevent(h->kq_fd, &h->kq_changes[r], 1, 0, 0, &tspec);
270
+					if (n==-1) {
271
+						if (unlikely(errno == EINTR))
272
+							goto retry2;
273
+					/* for a detailed explanation of what follows see
274
+						io_wait_loop_kqueue EV_ERROR case */
275
+						if (unlikely(!(errno == EBADF || errno == ENOENT)))
276
+							BUG("kq_ev_change: kevent flush changes failed:"
277
+									" (unexpected error) %s [%d] (%d/%lu)\n",
278
+										strerror(errno), errno,
279
+										r, (unsigned long)h->kq_nchanges);
280
+						continue; /* skip over it */
281
+					}
282
+				}
283
+			}
284
+		}
285
+		h->kq_nchanges=0; /* changes array is empty */
286
+	}
287
+	EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0,
288
+			KEV_UDATA_CAST data);
289
+	h->kq_nchanges++;
290
+	return 0;
291
+}
292
+#endif
293
+
294
+
295
+
296
+/* generic io_watch_add function
297
+ * Params:
298
+ *     h      - pointer to initialized io_wait handle
299
+ *     fd     - fd to watch
300
+ *     events - bitmap with the fd events for which the fd should be watched
301
+ *              (combination of POLLIN and POLLOUT)
302
+ *     type   - fd type (non 0 value, returned in the call to handle_io)
303
+ *     data   - pointer/private data returned in the handle_io call
304
+ * returns 0 on success, -1 on error
305
+ *
306
+ * WARNING: handle_io() can be called immediately (from io_watch_add()) so
307
+ *  make sure that any dependent init. (e.g. data stuff) is made before
308
+ *  calling io_watch_add
309
+ *
310
+ * this version should be faster than pointers to poll_method specific
311
+ * functions (it avoids functions calls, the overhead being only an extra
312
+ *  switch())*/
313
+inline static int io_watch_add(	io_wait_h* h,
314
+								int fd,
315
+								short events,
316
+								fd_type type,
317
+								void* data)
318
+{
319
+
320
+	/* helper macros */
321
+#define fd_array_setup(ev) \
322
+	do{ \
323
+		h->fd_array[h->fd_no].fd=fd; \
324
+		h->fd_array[h->fd_no].events=(ev); /* useless for select */ \
325
+		h->fd_array[h->fd_no].revents=0;     /* useless for select */ \
326
+	}while(0)
327
+	
328
+#define set_fd_flags(f) \
329
+	do{ \
330
+			flags=fcntl(fd, F_GETFL); \
331
+			if (flags==-1){ \
332
+				LM_ERR("fnctl: GETFL failed: %s [%d]\n", \
333
+					strerror(errno), errno); \
334
+				goto error; \
335
+			} \
336
+			if (fcntl(fd, F_SETFL, flags|(f))==-1){ \
337
+				LM_ERR("fnctl: SETFL failed: %s [%d]\n", \
338
+					strerror(errno), errno); \
339
+				goto error; \
340
+			} \
341
+	}while(0)
342
+	
343
+	
344
+	struct fd_map* e;
345
+	int flags;
346
+#ifdef HAVE_EPOLL
347
+	struct epoll_event ep_event;
348
+#endif
349
+#ifdef HAVE_DEVPOLL
350
+	struct pollfd pfd;
351
+#endif
352
+#if defined(HAVE_SIGIO_RT) || defined (HAVE_EPOLL)
353
+	int n;
354
+#endif
355
+#if defined(HAVE_SIGIO_RT)
356
+	int idx;
357
+	int check_io;
358
+	struct pollfd pf;
359
+	
360
+	check_io=0; /* set to 1 if we need to check for pre-existing queued
361
+				   io/data on the fd */
362
+	idx=-1;
363
+#endif
364
+	e=0;
365
+	/* sanity checks */
366
+	if (unlikely(fd==-1)){
367
+		LM_CRIT("fd is -1!\n");
368
+		goto error;
369
+	}
370
+	if (unlikely((events&(POLLIN|POLLOUT))==0)){
371
+		LM_CRIT("invalid events: 0x%0x\n", events);
372
+		goto error;
373
+	}
374
+	/* check if not too big */
375
+	if (unlikely(h->fd_no>=h->max_fd_no)){
376
+		LM_CRIT("maximum fd number exceeded: %d/%d\n", h->fd_no, h->max_fd_no);
377
+		goto error;
378
+	}
379
+	DBG("DBG: io_watch_add(%p, %d, %d, %p), fd_no=%d\n",
380
+			h, fd, type, data, h->fd_no);
381
+	/*  hash sanity check */
382
+	e=get_fd_map(h, fd);
383
+	if (unlikely(e && (e->type!=0 /*F_NONE*/))){
384
+		LM_ERR("trying to overwrite entry %d"
385
+			" watched for %x in the hash(%d, %d, %p) with (%d, %d, %p)\n",
386
+			fd, events, e->fd, e->type, e->data, fd, type, data);
387
+		e=0;
388
+		goto error;
389
+	}
390
+	
391
+	if (unlikely((e=hash_fd_map(h, fd, events, type, data))==0)){
392
+		LM_ERR("failed to hash the fd %d\n", fd);
393
+		goto error;
394
+	}
395
+	switch(h->poll_method){ /* faster then pointer to functions */
396
+		case POLL_POLL:
397
+#ifdef POLLRDHUP
398
+			/* listen to POLLRDHUP by default (if POLLIN) */
399
+			events|=((int)!(events & POLLIN) - 1) & POLLRDHUP;
400
+#endif /* POLLRDHUP */
401
+			fd_array_setup(events);
402
+			set_fd_flags(O_NONBLOCK);
403
+			break;
404
+#ifdef HAVE_SELECT
405
+		case POLL_SELECT:
406
+			fd_array_setup(events);
407
+			if (likely(events & POLLIN))
408
+				FD_SET(fd, &h->master_rset);
409
+			if (unlikely(events & POLLOUT))
410
+				FD_SET(fd, &h->master_wset);
411
+			if (h->max_fd_select<fd) h->max_fd_select=fd;
412
+			break;
413
+#endif
414
+#ifdef HAVE_SIGIO_RT
415
+		case POLL_SIGIO_RT:
416
+			fd_array_setup(events);
417
+			/* re-set O_ASYNC might be needed, if not done from
418
+			 * io_watch_del (or if somebody wants to add a fd which has
419
+			 * already O_ASYNC/F_SETSIG set on a duplicate)
420
+			 */
421
+			/* set async & signal */
422
+			if (fcntl(fd, F_SETOWN, my_pid())==-1){
423
+				LM_ERR("fnctl: SETOWN failed: %s [%d]\n",
424
+					strerror(errno), errno);
425
+				goto error;
426
+			}
427
+			if (fcntl(fd, F_SETSIG, h->signo)==-1){
428
+				LM_ERR("fnctl: SETSIG failed: %s [%d]\n",
429
+					strerror(errno), errno);
430
+				goto error;
431
+			}
432
+			/* set both non-blocking and async */
433
+			set_fd_flags(O_ASYNC| O_NONBLOCK);
434
+#ifdef EXTRA_DEBUG
435
+			DBG("io_watch_add: sigio_rt on f %d, signal %d to pid %d\n",
436
+					fd,  h->signo, my_pid());
437
+#endif
438
+			/* empty socket receive buffer, if buffer is already full
439
+			 * no more space to put packets
440
+			 * => no more signals are ever generated
441
+			 * also when moving fds, the freshly moved fd might have
442
+			 *  already some bytes queued, we want to get them now
443
+			 *  and not later -- andrei */
444
+			idx=h->fd_no;
445
+			check_io=1;
446
+			break;
447
+#endif
448
+#ifdef HAVE_EPOLL
449
+		case POLL_EPOLL_LT:
450
+			ep_event.events=
451
+#ifdef POLLRDHUP
452
+						/* listen for EPOLLRDHUP too */
453
+						((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
454
+#else /* POLLRDHUP */
455
+						(EPOLLIN & ((int)!(events & POLLIN)-1) ) |
456
+#endif /* POLLRDHUP */
457
+						(EPOLLOUT & ((int)!(events & POLLOUT)-1) );
458
+			ep_event.data.ptr=e;
459
+again1:
460
+			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
461
+			if (unlikely(n==-1)){
462
+				if (errno==EAGAIN) goto again1;
463
+				LM_ERR("epoll_ctl failed: %s [%d]\n", strerror(errno), errno);
464
+				goto error;
465
+			}
466
+			break;
467
+		case POLL_EPOLL_ET:
468
+			set_fd_flags(O_NONBLOCK);
469
+			ep_event.events=
470
+#ifdef POLLRDHUP
471
+						/* listen for EPOLLRDHUP too */
472
+						((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
473
+#else /* POLLRDHUP */
474
+						(EPOLLIN & ((int)!(events & POLLIN)-1) ) |
475
+#endif /* POLLRDHUP */
476
+						(EPOLLOUT & ((int)!(events & POLLOUT)-1) ) |
477
+						EPOLLET;
478
+			ep_event.data.ptr=e;
479
+again2:
480
+			n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
481
+			if (unlikely(n==-1)){
482
+				if (errno==EAGAIN) goto again2;
483
+				LM_ERR("epoll_ctl failed: %s [%d]\n", strerror(errno), errno);
484
+				goto error;
485
+			}
486
+			break;
487
+#endif
488
+#ifdef HAVE_KQUEUE
489
+		case POLL_KQUEUE:
490
+			if (likely( events & POLLIN)){
491
+				if (unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1))
492
+					goto error;
493
+			}
494
+			if (unlikely( events & POLLOUT)){
495
+				if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
496
+				{
497
+					if (likely(events & POLLIN)){
498
+						kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0);
499
+					}
500
+					goto error;
501
+				}
502
+			}
503
+			break;
504
+#endif
505
+#ifdef HAVE_DEVPOLL
506
+		case POLL_DEVPOLL:
507
+			pfd.fd=fd;
508
+			pfd.events=events;
509
+			pfd.revents=0;
510
+again_devpoll:
511
+			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
512
+				if (errno==EAGAIN) goto again_devpoll;
513
+				LM_ERR("/dev/poll write failed: %s [%d]\n",
514
+					strerror(errno), errno);
515
+				goto error;
516
+			}
517
+			break;
518
+#endif
519
+			
520
+		default:
521
+			LM_CRIT("no support for poll method  %s (%d)\n",
522
+				poll_method_str[h->poll_method], h->poll_method);
523
+			goto error;
524
+	}
525
+	
526
+	h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it
527
+				   has only informative value */
528
+#if defined(HAVE_SIGIO_RT)
529
+	if (check_io){
530
+		/* handle possible pre-existing events */
531
+		pf.fd=fd;
532
+		pf.events=events;
533
+check_io_again:
534
+		n=0;
535
+		while(e->type && ((n=poll(&pf, 1, 0))>0) &&
536
+				(handle_io(e, pf.revents, idx)>0) &&
537
+				(pf.revents & (e->events|POLLERR|POLLHUP)));
538
+		if (unlikely(e->type && (n==-1))){
539
+			if (errno==EINTR) goto check_io_again;
540
+			LM_ERR("check_io poll: %s [%d]\n", strerror(errno), errno);
541
+		}
542
+	}
543
+#endif
544
+	return 0;
545
+error:
546
+	if (e) unhash_fd_map(e);
547