瀏覽代碼

- kqueue support for freebsd, openbsd & netbsd added
- failing to set multicast parameters is no longer an error (will not prevent
ser from starting)

Andrei Pelinescu-Onciul 20 年之前
父節點
當前提交
741a993766
共有 5 個文件被更改,包括 310 次插入40 次删除
  1. 35 5
      Makefile.defs
  2. 108 3
      io_wait.c
  3. 140 13
      io_wait.h
  4. 18 9
      tcp_main.c
  5. 9 10
      udp_server.c

+ 35 - 5
Makefile.defs

@@ -39,6 +39,7 @@
 #  2004-12-19  amd64 transformed in x86_64 (andrei)
 #  2005-04-27  alpha support added (andrei)
 #  2005-06-01  use $(LOCALBASE) instead of /usr/{local,pkg} (andrei)
+#  2006-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
 
 
 # check if already included/exported
@@ -55,7 +56,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev8-new_tcp
+EXTRAVERSION = -dev9-new_tcp
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
@@ -63,6 +64,13 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/  \
 			-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" -e "s/cobalt/mips2/" \
 			-e s/amd64/x86_64/ )
 OSREL = $(shell uname -r)
+# numerical version (good for comparisons: A.B.C => A*1000000+B*1000+C)
+OSREL_N= $(shell echo $(OSREL) | sed -e 's/^[^0-9]*//' \
+		-e 's/^\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$$/\1/g' | \
+		(IFS=. read A B C ; R=0; \
+		[ -n "$$A" ] && R=`expr $$R \* 1000 + $$A` && \
+		[ -n "$$B" ] && R=`expr $$R \* 1000 + $$B` && \
+		[ -n "$$C" ] && R=`expr $$R \* 1000 + $$C`; echo $$R ) )
 
 # TLS support
 TLS ?= 
@@ -913,14 +921,17 @@ ifeq ($(OS), linux)
 		DEFS+= -DUSE_SYSV_SEM  # try posix sems
 		found_lock_method=yes
 	endif
-	# check for 2.6
-	ifneq ($(shell echo "$(OSREL)"|grep "^2\.6\."),)
+	# check for >= 2.5.44
+	ifeq ($(shell [ $(OSREL_N) -ge 2005044 ] && echo has_epoll), has_epoll)
 		ifeq ($(NO_EPOLL),)
 			DEFS+=-DHAVE_EPOLL
 		endif
 	endif
-	ifeq ($(NO_SIGIO),)
-		DEFS+=-DHAVE_SIGIO_RT
+	# check for >= 2.2.0
+	ifeq ($(shell [ $(OSREL_N) -ge 2002000 ] && echo has_sigio), has_sigio)
+		ifeq ($(NO_SIGIO),)
+			DEFS+=-DHAVE_SIGIO_RT
+		endif
 	endif
 	ifeq ($(NO_SELECT),)
 		DEFS+=-DHAVE_SELECT
@@ -971,6 +982,12 @@ ifeq ($(OS), freebsd)
 	else
 		LIBS= -lfl  #dlopen is in libc
 	endif
+	# check for ver >= 4.1
+	ifeq ($(shell [ $(OSREL_N) -gt 4001 ] && echo has_kqueue), has_kqueue)
+		ifeq ($(NO_KQUEUE),)
+			DEFS+=-DHAVE_KQUEUE
+		endif
+	endif
 	ifeq ($(NO_SELECT),)
 		DEFS+=-DHAVE_SELECT
 	endif
@@ -984,6 +1001,12 @@ ifeq ($(OS), openbsd)
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
 		found_lock_method=yes
 	endif
+	# check for ver >= 3.7
+	ifeq ($(shell [ $(OSREL_N) -ge 3007 ] && echo has_kqueue), has_kqueue)
+		ifeq ($(NO_KQUEUE),)
+			DEFS+=-DHAVE_KQUEUE
+		endif
+	endif
 	ifeq ($(NO_SELECT),)
 		DEFS+=-DHAVE_SELECT
 	endif
@@ -1016,6 +1039,13 @@ ifeq ($(OS), netbsd)
 		DEFS+= -DUSE_SYSV_SEM  # try pthread sems
 		found_lock_method=yes
 	endif
+	# check for ver >= 2.0.0
+$(warning OSREL_N=$(OSREL_N) , OSREL=$(OSREL) )
+	ifeq ($(shell [ $(OSREL_N) -ge 2000000 ] && echo has_kqueue), has_kqueue)
+		ifeq ($(NO_KQUEUE),)
+			DEFS+=-DHAVE_KQUEUE
+		endif
+	endif
 	ifeq ($(NO_SELECT),)
 		DEFS+=-DHAVE_SELECT
 	endif

+ 108 - 3
io_wait.c

@@ -32,6 +32,7 @@
  * History:
  * --------
  *  2005-06-15  created by andrei
+ *  2005-06-26  added kqueue (andrei)
  */
 
 
@@ -216,6 +217,33 @@ static void destroy_epoll(io_wait_h* h)
 
 
 
+#ifdef HAVE_KQUEUE
+/* kqueue specific init
+ * returns -1 on error, 0 on success */
+static int init_kqueue(io_wait_h* h)
+{
+	h->kq_fd=kqueue();
+	if (h->kq_fd==-1){
+		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
+				strerror(errno), errno);
+		return -1;
+	}
+	return 0;
+}
+
+
+
+static void destroy_kqueue(io_wait_h* h)
+{
+	if (h->kq_fd!=-1){
+		close(h->kq_fd);
+		h->kq_fd=-1;
+	}
+}
+#endif
+
+
+
 #ifdef HAVE_SELECT
 static int init_select(io_wait_h* h)
 {
@@ -284,10 +312,10 @@ char* check_poll_method(enum poll_types poll_method)
 			break;
 		case POLL_EPOLL_LT:
 		case POLL_EPOLL_ET:
-			/* only on 2.6 + */
 #ifndef HAVE_EPOLL
 			ret="epoll not supported, try re-compiling with -DHAVE_EPOLL";
 #else
+			/* only on 2.6 + */
 			if (os_ver<0x020542) /* if ver < 2.5.66 */
 			 	ret="epoll not supported on kernels < 2.6";
 #endif
@@ -296,8 +324,30 @@ char* check_poll_method(enum poll_types poll_method)
 #ifndef HAVE_SIGIO_RT
 			ret="sigio_rt not supported, try re-compiling with"
 				" -DHAVE_SIGIO_RT";
+#else
+			/* only on 2.2 +  ?? */
+			if (os_ver<0x020200) /* if ver < 2.2.0 */
+			 	ret="epoll not supported on kernels < 2.2 (?)";
 #endif
 			break;
+		case POLL_KQUEUE:
+#ifndef HAVE_KQUEUE
+			ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE";
+#else
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
+	#ifdef __OS_freebsd
+			if (os_ver<0x0401) /* if ver < 4.1 */
+				ret="kqueue not supported on FreeBSD < 4.1";
+	#elif defined (__OS_netbsd)
+			if (os_ver<0x020000) /* if ver < 2.0 */
+				ret="kqueue not supported on NetBSD < 2.0";
+	#elif defined (__OS_openbsd)
+			if (os_ver<0x0307) /* if ver < 3.7 ??? */
+				ret="kqueue not supported on OpenBSD < 3.7 (?)";
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
+#endif
+			break;	
+
 		default:
 			ret="unknown not supported method";
 	}
@@ -318,8 +368,22 @@ enum poll_types choose_poll_method()
 		poll_method=POLL_EPOLL_LT; /* or POLL_EPOLL_ET */
 		
 #endif
+#ifdef HAVE_KQUEUE
+	if (poll_method==0)
+		/* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */
+	#ifdef __OS_freebsd
+		if (os_ver>=0x0401) /* if ver >= 4.1 */
+	#elif defined (__OS_netbsd)
+		if (os_ver>=0x020000) /* if ver >= 2.0 */
+	#elif defined (__OS_openbsd)
+		if (os_ver>=0x0307) /* if ver >= 3.7 */
+	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
+			poll_method=POLL_KQUEUE;
+#endif
 #ifdef  HAVE_SIGIO_RT
-		if (poll_method==0) poll_method=POLL_SIGIO_RT;
+		if (poll_method==0) 
+			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
+				poll_method=POLL_SIGIO_RT;
 #endif
 		if (poll_method==0) poll_method=POLL_POLL;
 	return poll_method;
@@ -369,7 +433,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
 #ifdef HAVE_EPOLL
 	h->epfd=-1;
 #endif
-	
+#ifdef HAVE_KQUEUE
+	h->kq_fd=-1;
+#endif
 	poll_err=check_poll_method(poll_method);
 	
 	/* set an appropiate poll method */
@@ -445,6 +511,32 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
 				goto error;
 			}
 			break;
+#endif
+#ifdef HAVE_KQUEUE
+		case POLL_KQUEUE:
+			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
+			if (h->kq_array==0){
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
+							" kqueue event array\n");
+				goto error;
+			}
+			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
+			h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
+										h->kq_changes_size);
+			if (h->kq_changes==0){
+				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
+							" kqueue changes array\n");
+				goto error;
+			}
+			h->kq_nchanges=0;
+			memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
+			memset((void*)h->kq_changes, 0,
+						sizeof(*(h->kq_changes))* h->kq_changes_size);
+			if (init_kqueue(h)<0){
+				LOG(L_CRIT, "ERROR: init_io_wait: kqueue init failed\n");
+				goto error;
+			}
+			break;
 #endif
 		default:
 			LOG(L_CRIT, "BUG: init_io_wait: unknown/unsupported poll"
@@ -473,6 +565,19 @@ void destroy_io_wait(io_wait_h* h)
 			}
 		break;
 #endif
+#ifdef HAVE_KQUEUE
+		case POLL_KQUEUE:
+			destroy_kqueue(h);
+			if (h->kq_array){
+				local_free(h->kq_array);
+				h->kq_array=0;
+			}
+			if (h->kq_changes){
+				local_free(h->kq_changes);
+				h->kq_changes=0;
+			}
+			break;
+#endif
 #ifdef HAVE_SIGIO_RT
 		case POLL_SIGIO_RT:
 			destroy_sigio(h);

+ 140 - 13
io_wait.h

@@ -46,6 +46,7 @@
  * History:
  * --------
  *  2005-06-13  created by andrei
+ *  2005-06-26  added kqueue (andrei)
  */
 
 
@@ -64,6 +65,11 @@
 #ifdef HAVE_EPOLL
 #include <sys/epoll.h>
 #endif
+#ifdef HAVE_KQUEUE
+#include <sys/types.h> /* needed on freebsd */
+#include <sys/event.h>
+#include <sys/time.h>
+#endif
 #ifdef HAVE_SELECT
 /* needed on openbsd for select*/
 #include <sys/time.h> 
@@ -103,6 +109,19 @@ struct fd_map{
 };
 
 
+#ifdef HAVE_KQUEUE
+#ifndef KQ_CHANGES_ARRAY_SIZE
+#define KQ_CHANGES_ARRAY_SIZE 128
+
+#ifdef __OS_netbsd
+#define KEV_UDATA_CAST (intptr_t)
+#else
+#define KEV_UDATA_CAST
+#endif
+
+#endif
+#endif
+
 
 /* handler structure */
 struct io_wait_handler{
@@ -114,6 +133,13 @@ struct io_wait_handler{
 	sigset_t sset; /* signal mask for sigio & sigrtmin */
 	int signo;     /* real time signal used */
 #endif
+#ifdef HAVE_KQUEUE
+	struct kevent* kq_array;   /* used for the eventlist*/
+	struct kevent* kq_changes; /* used for the changelist */
+	size_t kq_nchanges;
+	size_t kq_changes_size; /* size of the changes array */
+	int kq_fd;
+#endif
 #ifdef HAVE_SELECT
 	fd_set master_set;
 	int max_fd_select; /* maximum select used fd */
@@ -185,6 +211,43 @@ int handle_io(struct fd_map* fm, int idx);
 
 
 
+#ifdef HAVE_KQUEUE
+/*
+ * kqueue specific function: register a change
+ * (adds a change to the kevent change array, and if full flushes it first)
+ * returns: -1 on error, 0 on success
+ */
+static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag, 
+								void* data)
+{
+	int n;
+	struct timespec tspec;
+
+	if (h->kq_nchanges>=h->kq_changes_size){
+		/* changes array full ! */
+		LOG(L_WARN, "WARNING: kq_ev_change: kqueue changes array full"
+					" trying to flush...\n");
+		tspec.tv_sec=0;
+		tspec.tv_nsec=0;
+again:
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec);
+		if (n==-1){
+			if (errno==EINTR) goto again;
+			LOG(L_ERR, "ERROR: io_watch_add: kevent flush changes "
+						" failed: %s [%d]\n", strerror(errno), errno);
+			return -1;
+		}
+		h->kq_nchanges=0; /* changes array is empty */
+	}
+	EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0,
+			KEV_UDATA_CAST data);
+	h->kq_nchanges++;
+	return 0;
+}
+#endif
+
+
+
 /* generic io_watch_add function
  * returns 0 on success, -1 on error
  *
@@ -235,7 +298,7 @@ inline static int io_watch_add(	io_wait_h* h,
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
 		goto error;
 	}
-	/* add it to the poll fd array */
+	/* check if not too big */
 	if (h->fd_no>=h->max_fd_no){
 		LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:"
 				" %d/%d\n", h->fd_no, h->max_fd_no);
@@ -320,6 +383,12 @@ again2:
 				goto error;
 			}
 			break;
+#endif
+#ifdef HAVE_KQUEUE
+		case POLL_KQUEUE:
+			if (kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1)
+				goto error;
+			break;
 #endif
 		default:
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
@@ -328,7 +397,7 @@ again2:
 			goto error;
 	}
 	
-	h->fd_no++; /* "activate" changes, for epoll it
+	h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it
 				   has only informative value */
 	return 0;
 error:
@@ -339,12 +408,19 @@ error:
 
 
 
-/* parameters: fd and index in the fd_array
- * if index==-1, it fd_array will be searched for the corresponding fd
- * entry (slower but unavoidable in some cases)
- * index is not used (no fd_arry) for epoll, /dev/poll and kqueue
+#define IO_FD_CLOSING 16
+/* parameters:    h - handler 
+ *               fd - file descriptor
+ *            index - index in the fd_array if known, -1 if not
+ *                    (if index==-1 fd_array will be searched for the
+ *                     corresponding fd* entry -- slower but unavoidable in 
+ *                     some cases). index is not used (no fd_array) for epoll,
+ *                     /dev/poll and kqueue
+ *            flags - optimization flags, e.g. IO_FD_CLOSING, the fd was 
+ *                    or will shortly be closed, in some cases we can avoid
+ *                    extra remove operations (e.g.: epoll, kqueue, sigio)
  * returns 0 if ok, -1 on error */
-inline static int io_watch_del(io_wait_h* h, int fd, int idx)
+inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
 {
 	
 #define fix_fd_array \
@@ -416,11 +492,21 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx)
 #ifdef HAVE_EPOLL
 		case POLL_EPOLL_LT:
 		case POLL_EPOLL_ET:
-			n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
-			if (n==-1){
-				LOG(L_ERR, "ERROR: io_watch_del: removing fd from"
-					" epoll list failed: %s [%d]\n", strerror(errno), errno);
-				goto error;
+			if (!(flags & IO_FD_CLOSING)){
+				n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
+				if (n==-1){
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll "
+							"list failed: %s [%d]\n", strerror(errno), errno);
+					goto error;
+				}
+			}
+			break;
+#endif
+#ifdef HAVE_KQUEUE
+		case POLL_KQUEUE:
+			if (!(flags & IO_FD_CLOSING)){
+				if (kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0)==-1)
+					goto error;
 			}
 			break;
 #endif
@@ -528,7 +614,7 @@ again:
 		if (n==-1){
 			if (errno==EINTR) goto again; /* signal, ignore it */
 			else{
-				LOG(L_ERR, "ERROR:io_wait_loop_epoll_et: epoll_wait:"
+				LOG(L_ERR, "ERROR:io_wait_loop_epoll: epoll_wait:"
 						" %s [%d]\n", strerror(errno), errno);
 				goto error;
 			}
@@ -544,6 +630,47 @@ error:
 
 
 
+#ifdef HAVE_KQUEUE
+inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
+{
+	int n, r;
+	struct timespec tspec;
+	
+	tspec.tv_sec=t;
+	tspec.tv_nsec=0;
+again:
+		n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges,  h->kq_array,
+					h->fd_no, &tspec);
+		if (n==-1){
+			if (errno==EINTR) goto again; /* signal, ignore it */
+			else{
+				LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:"
+						" %s [%d]\n", strerror(errno), errno);
+				goto error;
+			}
+		}
+		h->kq_nchanges=0; /* reset changes array */
+		for (r=0; r<n; r++){
+			if (h->kq_array[r].flags & EV_ERROR){
+				/* error in changes: we ignore it, it can be caused by
+				   trying to remove an already closed fd: race between
+				   adding smething to the changes array, close() and
+				   applying the changes */
+				LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on "
+							"fd %d: %s [%d]\n", h->kq_array[r].ident,
+							strerror(h->kq_array[r].data),
+							h->kq_array[r].data);
+			}else /* READ/EOF */
+				while((handle_io((struct fd_map*)h->kq_array[r].udata, -1)>0)
+						&& repeat);
+		}
+error:
+	return n;
+}
+#endif
+
+
+
 #ifdef HAVE_SIGIO_RT
 /* sigio rt version has no repeat (it doesn't make sense)*/
 inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t)

+ 18 - 9
tcp_main.c

@@ -54,6 +54,7 @@
  *  2004-11-08  dropped find_tcp_si and replaced with find_si (andrei)
  *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
  *               signals, poll & select (andrei)
+ *  2005-06-26  *bsd kqueue support (andrei)
  */
 
 
@@ -1073,7 +1074,7 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, int fd_i)
 	}
 	/* pass it to child, so remove it from the io watch list */
 	DBG("handle_tcpconn_ev: data available on %p %d\n", tcpconn, tcpconn->s);
-	if (io_watch_del(&io_h, tcpconn->s, fd_i)==-1) goto error;
+	if (io_watch_del(&io_h, tcpconn->s, fd_i, 0)==-1) goto error;
 	tcpconn_ref(tcpconn); /* refcnt ++ */
 	if (send2child(tcpconn)<0){
 		LOG(L_ERR,"ERROR: handle_tcpconn_ev: no children available\n");
@@ -1126,8 +1127,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 			DBG("DBG: handle_tcp_child: dead tcp child %d (pid %d, no %d)"
 					" (shutting down?)\n", (int)(tcp_c-&tcp_children[0]), 
 					tcp_c->pid, tcp_c->proc_no );
-						/* don't listen on it any more */
-			io_watch_del(&io_h, tcp_c->unix_sock, fd_i); 
+			/* don't listen on it any more */
+			io_watch_del(&io_h, tcp_c->unix_sock, fd_i, 0); 
 			goto error; /* eof. so no more io here, it's ok to return error */
 		}else if (bytes<0){
 			/* EAGAIN is ok if we try to empty the buffer
@@ -1186,9 +1187,9 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i)
 				tcp_c->busy--;
 				/* main doesn't listen on it => we don't have to delete it
 				 if (tcpconn->s!=-1)
-					io_watch_del(&io_h, tcpconn->s, -1);
+					io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
 				*/
-				tcpconn_destroy(tcpconn);
+				tcpconn_destroy(tcpconn); /* closes also the fd */
 				break;
 		default:
 				LOG(L_CRIT, "BUG: handle_tcp_child:  unknown cmd %d"
@@ -1244,7 +1245,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
 			DBG("DBG: handle_ser_child: dead child %d, pid %d"
 					" (shutting down?)\n", (int)(p-&pt[0]), p->pid);
 			/* don't listen on it any more */
-			io_watch_del(&io_h, p->unix_sock, fd_i);
+			io_watch_del(&io_h, p->unix_sock, fd_i, 0);
 			goto error; /* child dead => no further io events from it */
 		}else if (bytes<0){
 			/* EAGAIN is ok if we try to empty the buffer
@@ -1283,8 +1284,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i)
 	switch(cmd){
 		case CONN_ERROR:
 			if (tcpconn->s!=-1)
-				io_watch_del(&io_h, tcpconn->s, -1);
-			tcpconn_destroy(tcpconn);
+				io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING);
+			tcpconn_destroy(tcpconn); /* will close also the fd */
 			break;
 		case CONN_GET_FD:
 			/* send the requested FD  */
@@ -1391,7 +1392,7 @@ static void tcpconn_timeout()
 #endif
 				_tcpconn_rm(c);
 				if (fd>0) {
-					io_watch_del(&io_h, fd, -1);
+					io_watch_del(&io_h, fd, -1, IO_FD_CLOSING);
 					close(fd);
 				}
 			}
@@ -1506,6 +1507,14 @@ void tcp_main_loop()
 				tcpconn_timeout();
 			}
 			break;
+#endif
+#ifdef HAVE_KQUEUE
+		case POLL_KQUEUE:
+			while(1){
+				io_wait_loop_kqueue(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
+				tcpconn_timeout();
+			}
+			break;
 #endif
 		default:
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "

+ 9 - 10
udp_server.c

@@ -35,6 +35,7 @@
  *  2004-07-05  udp_rcv_loop: drop packets with 0 src port + error msg.
  *              cleanups (andrei)
  *  2005-03-10  multicast options are now set for all the udp sockets (andrei)
+ *  2005-06-26  failure to set mcast options is not an error anymore (andrei)
  */
 
 
@@ -319,32 +320,30 @@ int udp_init(struct socket_info* sock_info)
 	if (addr->s.sa_family==AF_INET){
 		if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_LOOP, 
 						&mcast_loopback, sizeof(mcast_loopback))==-1){
-			LOG(L_ERR, "ERROR: udp_init: setsockopt(IP_MULTICAST_LOOP): %s\n",
-						strerror(errno));
-			goto error;
+			LOG(L_WARN, "WARNING: udp_init: setsockopt(IP_MULTICAST_LOOP):"
+						" %s\n", strerror(errno));
+			/* it's only a warning because we might get this error if the
+			  network interface doesn't support multicasting -- andrei */
 		}
 		if (mcast_ttl>=0){
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_TTL,
 						&mcast_ttl, sizeof(mcast_ttl))==-1){
-				LOG(L_ERR, "ERROR: udp_init: setsockopt (IP_MULTICAST_TTL):"
+				LOG(L_WARN, "WARNING: udp_init: setsockopt (IP_MULTICAST_TTL):"
 						" %s\n", strerror(errno));
-				goto error;
 			}
 		}
 #ifdef USE_IPV6
 	} else if (addr->s.sa_family==AF_INET6){
 		if (setsockopt(sock_info->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
 						&mcast_loopback, sizeof(mcast_loopback))==-1){
-			LOG(L_ERR, "ERROR: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
+			LOG(L_WARN, "WARNING: udp_init: setsockopt (IPV6_MULTICAST_LOOP):"
 					" %s\n", strerror(errno));
-			goto error;
 		}
 		if (mcast_ttl>=0){
 			if (setsockopt(sock_info->socket, IPPROTO_IP, IPV6_MULTICAST_HOPS,
 							&mcast_ttl, sizeof(mcast_ttl))==-1){
-				LOG(L_ERR, "ERROR: udp_init: setssckopt (IPV6_MULTICAST_HOPS):"
-						" %s\n", strerror(errno));
-				goto error;
+				LOG(L_WARN, "WARNING: udp_init: setssckopt "
+						"(IPV6_MULTICAST_HOPS): %s\n", strerror(errno));
 			}
 		}
 #endif /* USE_IPV6*/