commit 292879aca48e7b28d592cff99361ba73e01d0aa8 from: Alexander Barton date: Sun Dec 26 00:14:33 2004 UTC Added support for the Howl (http://www.porchdogsoft.com/products/howl/) Rendezvous API, in addition to the API of Apple (Mac OS X). commit - dcb9e2a004874675dfae2e3d3f886b70554b459b commit + 292879aca48e7b28d592cff99361ba73e01d0aa8 blob - cf9efd3cf995c59750fe2bca0cbf2e63759ef912 blob + c5b9ddcd6c780c8d3c4522350a6d76832fac4e7f --- ChangeLog +++ ChangeLog @@ -12,6 +12,9 @@ ngIRCd CVSHEAD + - Added support for the Howl (http://www.porchdogsoft.com/products/howl/) + Rendezvous API, in addition to the API of Apple (Mac OS X). The available + APU will be autodetected when you call "./configure --with-rendezvous". - Made ngIRCd compile on HP/UX 10.20 with native HP pre-ANSI C compiler and most probably other older C compilers on other systems. - When the daemon should switch to another user ID (ServerID is defined in @@ -550,4 +553,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: ChangeLog,v 1.247 2004/12/25 00:22:00 alex Exp $ +$Id: ChangeLog,v 1.248 2004/12/26 00:14:33 alex Exp $ blob - 6e2369f2910ecfb1cd60de291387b07ba54e783f blob + 09b9a62f2ccd4d3a07c7f97943f7d824a32adc93 --- NEWS +++ NEWS @@ -10,6 +10,12 @@ -- NEWS -- +ngIRCd CVSHEAD + + - Added support for the Howl (http://www.porchdogsoft.com/products/howl/) + Rendezvous API, in addition to the API of Apple (Mac OS X). The available + APU will be autodetected when you call "./configure --with-rendezvous". + ngIRCd 0.8.0 (2004-06-26) - Two new configuration options: "ChrootDir" and "MotdPhrase", thanks to @@ -189,4 +195,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: NEWS,v 1.66 2004/07/03 18:35:41 alex Exp $ +$Id: NEWS,v 1.67 2004/12/26 00:14:33 alex Exp $ blob - 64179058def62578ce612f5df110b7ebe4bbae39 blob + cbd9fec290b035378330ba7f4f2bc967633107d9 --- configure.in +++ configure.in @@ -8,7 +8,7 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: configure.in,v 1.103 2004/05/15 12:24:30 alex Exp $ +# $Id: configure.in,v 1.104 2004/12/26 00:14:33 alex Exp $ # # -- Initialisation -- @@ -195,16 +195,42 @@ x_rendezvous_on=no AC_ARG_WITH(rendezvous, [ --with-rendezvous enable support for "Rendezvous"], [ if test "$withval" = "yes"; then - AC_CHECK_FUNCS(DNSServiceRegistrationCreate, x_rendezvous_on=yes, - AC_MSG_ERROR([Can't enable Rendezvous!]) - ) + AC_CHECK_FUNCS(DNSServiceRegistrationCreate, x_rendezvous_on=osx, + [ + AC_CHECK_LIB(pthread, pthread_mutexattr_init) + AC_CHECK_LIB(howl, sw_discovery_init) + AC_CHECK_FUNCS(sw_discovery_init, \ + x_rendezvous_on=howl, \ + AC_MSG_ERROR([Can't enable Rendezvous!])) + ]) fi ] ) -if test "$x_rendezvous_on" = "yes"; then - AC_DEFINE(RENDEZVOUS, 1) +if test "$x_rendezvous_on" = "osx"; then AC_CHECK_HEADERS([DNSServiceDiscovery/DNSServiceDiscovery.h \ mach/port.h],,AC_MSG_ERROR([required C header missing!])) + AC_DEFINE(RENDEZVOUS, 1) +fi +if test "$x_rendezvous_on" = "howl"; then + for dir in /usr/local/include /usr/local/include/howl* \ + /usr/include /usr/include/howl*; do + test -d "$dir" || continue + AC_MSG_CHECKING([for Howl headers in $dir]) + if test -f "$dir/rendezvous/rendezvous.h"; then + if test "$dir" != "/usr/local/include" -a \ + "$dir" != "/usr/include"; then + CFLAGS="$CFLAGS -I$dir" + CPPFLAGS="-I$dir $CPPFLAGS" + fi + AC_MSG_RESULT(yes) + break + else + AC_MSG_RESULT(no) + fi + done + AC_CHECK_HEADERS([rendezvous/rendezvous.h],, \ + AC_MSG_ERROR([required C header missing!])) + AC_DEFINE(RENDEZVOUS, 1) fi x_identauth_on=no @@ -348,7 +374,7 @@ test "$x_strict_rfc_on" = "yes" \ || echo "no" echo $ECHO_N " Rendezvous support: $ECHO_C" -test "$x_rendezvous_on" = "yes" \ +test "$x_rendezvous_on" = "osx" -o "$x_rendezvous_on" = "howl" \ && echo $ECHO_N "yes $ECHO_C" \ || echo $ECHO_N "no $ECHO_C" echo $ECHO_N " IRC+ protocol: $ECHO_C" blob - 323b07df26d1233f1772b91752427ebdab7abfb0 blob + 720f5dfe57d3368f5300c13d3bfec725a060f8cb --- src/ngircd/rendezvous.c +++ src/ngircd/rendezvous.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2004 by Alexander Barton (alex@barton.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -8,7 +8,11 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * Rendezvous service registration (using Mach Ports, e.g. Mac OS X) + * Rendezvous service registration. + * + * Supported APIs are: + * - Apple Mac OS X + * - Howl */ @@ -17,7 +21,7 @@ #ifdef RENDEZVOUS -static char UNUSED id[] = "$Id: rendezvous.c,v 1.2 2003/03/27 01:24:32 alex Exp $"; +static char UNUSED id[] = "$Id: rendezvous.c,v 1.3 2004/12/26 00:14:33 alex Exp $"; #include "imp.h" #include @@ -34,6 +38,10 @@ static char UNUSED id[] = "$Id: rendezvous.c,v 1.2 200 #include #endif +#ifdef HAVE_RENDEZVOUS_RENDEZVOUS_H +#include +#endif + #include "defines.h" #include "log.h" @@ -41,36 +49,79 @@ static char UNUSED id[] = "$Id: rendezvous.c,v 1.2 200 #include "rendezvous.h" +#if defined(HAVE_DNSSERVICEREGISTRATIONCREATE) +# define APPLE +#elif defined(HAVE_SW_DISCOVERY_INIT) +# define HOWL +#else +# error "Can't detect Rendezvous API!?" +#endif + + +#define MAX_RENDEZVOUS 1000 + typedef struct _service { + CHAR Desc[CLIENT_ID_LEN]; +#ifdef APPLE dns_service_discovery_ref Discovery_Ref; mach_port_t Mach_Port; - CHAR Desc[CLIENT_ID_LEN]; +#endif +#ifdef HOWL + sw_discovery_oid Id; +#endif } SERVICE; +LOCAL SERVICE My_Rendezvous[MAX_RENDEZVOUS]; -LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context ); + LOCAL VOID Unregister( INT Idx ); -#define MAX_RENDEZVOUS 1000 +/* -- Apple API -- */ + +#ifdef APPLE + #define MAX_MACH_MSG_SIZE 512 +LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context ); -LOCAL SERVICE My_Rendezvous[MAX_RENDEZVOUS]; +#endif /* Apple */ +/* -- Howl API -- */ + +#ifdef HOWL + +#include + +LOCAL sw_discovery My_Discovery_Session = NULL; +LOCAL pthread_t My_Howl_Thread; +LOCAL BOOLEAN My_Howl_Thread_Created = FALSE; + +LOCAL sw_result HOWL_API Registration_Reply_Handler( sw_discovery Session, sw_discovery_publish_status Status, sw_discovery_oid Id, sw_opaque Extra ); + +LOCAL VOID* Howl_Thread( VOID *x ); + +#endif /* Howl */ + + GLOBAL VOID Rendezvous_Init( VOID ) { /* Initialize structures */ INT i; - for( i = 0; i < MAX_RENDEZVOUS; i++ ) +#ifdef HOWL + if( sw_discovery_init( &My_Discovery_Session ) != SW_OKAY ) { - My_Rendezvous[i].Discovery_Ref = 0; - My_Rendezvous[i].Mach_Port = 0; + Log( LOG_EMERG, "Can't initialize Rendezvous (Howl): sw_discovery_init() failed!" ); + Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); + exit( 1 ); } +#endif + + for( i = 0; i < MAX_RENDEZVOUS; i++ ) My_Rendezvous[i].Desc[0] = '\0'; } /* Rendezvous_Init */ @@ -82,8 +133,18 @@ GLOBAL VOID Rendezvous_Exit( VOID ) for( i = 0; i < MAX_RENDEZVOUS; i++ ) { - if( My_Rendezvous[i].Discovery_Ref ) Unregister( i ); + if( My_Rendezvous[i].Desc[0] ) Unregister( i ); } + +#ifdef HOWL + if( My_Howl_Thread_Created ) + { + Log( LOG_DEBUG, "Rendezvous: Canceling management thread ..." ); + pthread_cancel( My_Howl_Thread ); + } + + sw_discovery_fina( My_Discovery_Session ); +#endif } /* Rendezvous_Exit */ @@ -94,7 +155,7 @@ GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR * INT i; /* Search free port structure */ - for( i = 0; i < MAX_RENDEZVOUS; i++ ) if( ! My_Rendezvous[i].Discovery_Ref ) break; + for( i = 0; i < MAX_RENDEZVOUS; i++ ) if( ! My_Rendezvous[i].Desc[0] ) break; if( i >= MAX_RENDEZVOUS ) { Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: limit (%d) reached!", Name, MAX_RENDEZVOUS ); @@ -102,11 +163,13 @@ GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR * } strlcpy( My_Rendezvous[i].Desc, Name, sizeof( My_Rendezvous[i].Desc )); +#ifdef APPLE /* Register new service */ - My_Rendezvous[i].Discovery_Ref = DNSServiceRegistrationCreate( Name, Type, "", htonl( Port ), "", Registration_Reply_Handler, My_Rendezvous[i].Desc ); + My_Rendezvous[i].Discovery_Ref = DNSServiceRegistrationCreate( Name, Type, "", htonl( Port ), "", Registration_Reply_Handler, &My_Rendezvous[i] ); if( ! My_Rendezvous[i].Discovery_Ref ) { Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: can't register service!", My_Rendezvous[i].Desc ); + My_Rendezvous[i].Desc[0] = '\0'; return FALSE; } @@ -117,9 +180,20 @@ GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR * Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: got no Mach Port!", My_Rendezvous[i].Desc ); /* Here we actually leek a descriptor :-( */ My_Rendezvous[i].Discovery_Ref = 0; + My_Rendezvous[i].Desc[0] = '\0'; return FALSE; } +#endif /* Apple */ +#ifdef HOWL + if( sw_discovery_publish( My_Discovery_Session, 0, Name, Type, NULL, NULL, Port, NULL, 0, Registration_Reply_Handler, &My_Rendezvous[i], &My_Rendezvous[i].Id ) != SW_OKAY ) + { + Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: can't register service!", My_Rendezvous[i].Desc ); + My_Rendezvous[i].Desc[0] = '\0'; + return FALSE; + } +#endif /* Howl */ + Log( LOG_DEBUG, "Rendezvous: Registering \"%s\" ...", My_Rendezvous[i].Desc ); return TRUE; } /* Rendezvous_Register */ @@ -154,7 +228,7 @@ GLOBAL VOID Rendezvous_UnregisterListeners( VOID ) for( i = 0; i < MAX_RENDEZVOUS; i++ ) { - if( My_Rendezvous[i].Discovery_Ref ) Unregister( i ); + if( My_Rendezvous[i].Desc[0] ) Unregister( i ); } } /* Rendezvous_UnregisterListeners */ @@ -164,6 +238,7 @@ GLOBAL VOID Rendezvous_Handler( VOID ) /* Handle all Rendezvous stuff; this function must be called * periodically from the run loop of the main program */ +#ifdef APPLE INT i; CHAR buffer[MAX_MACH_MSG_SIZE]; mach_msg_return_t result; @@ -181,19 +256,57 @@ GLOBAL VOID Rendezvous_Handler( VOID ) if( result == MACH_MSG_SUCCESS ) DNSServiceDiscovery_handleReply( msg ); #ifdef DEBUG else if( result != MACH_RCV_TIMED_OUT ) Log( LOG_DEBUG, "mach_msg(): %ld", (LONG)result ); -#endif +#endif /* Debug */ } +#endif /* Apple */ + +#ifdef HOWL + if( My_Discovery_Session != NULL && My_Howl_Thread_Created == FALSE ) + { + /* Create POSIX thread for sw_discovery_run() */ + Log( LOG_DEBUG, "Rendezvous: Creating management thread ..." ); + pthread_create( &My_Howl_Thread, NULL, Howl_Thread, NULL ); + My_Howl_Thread_Created = TRUE; + } +#endif } /* Rendezvous_Handler */ +LOCAL VOID Unregister( INT Idx ) +{ + /* Unregister service */ + +#ifdef APPLE + DNSServiceDiscoveryDeallocate( My_Rendezvous[Idx].Discovery_Ref ); +#endif /* Apple */ + +#ifdef HOWL + if( sw_discovery_cancel( My_Discovery_Session, My_Rendezvous[Idx].Id ) != SW_OKAY ) + { + Log( LOG_ERR, "Rendezvous: Failed to unregister \"%s\"!", My_Rendezvous[Idx].Desc ); + return; + } +#endif /* Howl */ + + Log( LOG_INFO, "Unregistered \"%s\" from Rendezvous.", My_Rendezvous[Idx].Desc ); + My_Rendezvous[Idx].Desc[0] = '\0'; +} /* Unregister */ + + +/* -- Apple API -- */ + +#ifdef APPLE + + LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context ) { + SERVICE *s = (SERVICE *)Context; CHAR txt[50]; if( ErrCode == kDNSServiceDiscoveryNoError ) { /* Success! */ - Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", Context ? Context : "NULL" ); + Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", s->Desc ); return; } @@ -209,20 +322,61 @@ LOCAL VOID Registration_Reply_Handler( DNSServiceRegis sprintf( txt, "error code %ld!", (LONG)ErrCode ); } - Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", Context ? Context : "NULL", txt ); + Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", s->Desc, txt ); + s->Desc[0] = '\0'; } /* Registration_Reply_Handler */ -LOCAL VOID Unregister( INT Idx ) +#endif /* Apple */ + + +/* -- Howl API -- */ + +#ifdef HOWL + + +LOCAL sw_result HOWL_API Registration_Reply_Handler( sw_discovery Session, sw_discovery_publish_status Status, UNUSED sw_discovery_oid Id, sw_opaque Extra ) { - /* Unregister service */ + SERVICE *s = (SERVICE *)Extra; + CHAR txt[50]; - DNSServiceDiscoveryDeallocate( My_Rendezvous[Idx].Discovery_Ref ); - Log( LOG_INFO, "Unregistered \"%s\" from Rendezvous.", My_Rendezvous[Idx].Desc ); - My_Rendezvous[Idx].Discovery_Ref = 0; -} /* Unregister */ + assert( Session == My_Discovery_Session ); + assert( Extra != NULL ); + if( Status == SW_DISCOVERY_PUBLISH_STARTED || Status == SW_DISCOVERY_PUBLISH_STOPPED ) + { + /* Success! */ + Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", s->Desc ); + return SW_OKAY; + } + + switch( Status ) + { + case SW_DISCOVERY_PUBLISH_NAME_COLLISION: + strcpy( txt, "name conflict!" ); + break; + default: + sprintf( txt, "error code %ld!", (LONG)Status ); + } + Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", s->Desc, txt ); + s->Desc[0] = '\0'; + + return SW_OKAY; +} /* Registration_Reply_Handler */ + + +LOCAL VOID *Howl_Thread( VOID *x ) +{ + assert( x == NULL ); + sw_discovery_run( My_Discovery_Session ); + pthread_exit( NULL ); +} /* Howl_Thread */ + + +#endif /* Howl */ + + #endif /* RENDEZVOUS */