]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/rendezvous.c
New configuration option "NoZeroConf" to disable ZeroConf registration
[ngircd-alex.git] / src / ngircd / rendezvous.c
index 323b07df26d1233f1772b91752427ebdab7abfb0..2d9ae6993d08b1c5666a5fda10161016f111c57e 100644 (file)
@@ -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,16 +8,20 @@
  * (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
  */
 
 
 #include "portab.h"
 
-#ifdef RENDEZVOUS
+#ifdef ZEROCONF
 
 
-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.8 2006/05/10 21:24:01 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -34,6 +38,10 @@ static char UNUSED id[] = "$Id: rendezvous.c,v 1.2 2003/03/27 01:24:32 alex Exp
 #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
 #endif
 
+#ifdef HAVE_RENDEZVOUS_RENDEZVOUS_H
+#include <rendezvous/rendezvous.h>
+#endif
+
 #include "defines.h"
 #include "log.h"
 
@@ -41,73 +49,128 @@ static char UNUSED id[] = "$Id: rendezvous.c,v 1.2 2003/03/27 01:24:32 alex Exp
 #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;
 
+static SERVICE My_Rendezvous[MAX_RENDEZVOUS];
 
-LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context );
-LOCAL VOID Unregister( INT Idx );
 
+static void Unregister( int Idx );
+
+
+/* -- Apple API -- */
+
+#ifdef APPLE
 
-#define MAX_RENDEZVOUS 1000
 #define MAX_MACH_MSG_SIZE 512
 
+static void Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, void *Context );
+
+#endif /* Apple */
+
+
+/* -- Howl API -- */
+
+#ifdef HOWL
+
+static sw_discovery My_Discovery_Session = NULL;
+static sw_salt My_Salt;
+
+static sw_result HOWL_API Registration_Reply_Handler( sw_discovery Session, sw_discovery_publish_status Status, sw_discovery_oid Id, sw_opaque Extra );
 
-LOCAL SERVICE My_Rendezvous[MAX_RENDEZVOUS];
+#endif /* Howl */
 
 
-GLOBAL VOID Rendezvous_Init( VOID )
+GLOBAL void Rendezvous_Init( void )
 {
        /* Initialize structures */
 
-       INT i;
+       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 );
+       }
+
+       if( sw_discovery_salt( My_Discovery_Session, &My_Salt ) != SW_OKAY )
+       {
+               Log( LOG_EMERG, "Can't initialize Rendezvous (Howl): sw_discovery_salt() 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 */
 
 
-GLOBAL VOID Rendezvous_Exit( VOID )
+GLOBAL void Rendezvous_Exit( void )
 {
        /* Clean up & exit module */
 
-       INT i;
+       int i;
 
        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
+       sw_discovery_fina( My_Discovery_Session );
+#endif
 } /* Rendezvous_Exit */
 
 
-GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR *Type, UINT Port )
+/**
+ * Register ZeroConf service
+ */
+GLOBAL bool Rendezvous_Register( char *Name, char *Type, UINT16 Port )
 {
-       /* Register new service */
+       int i;
 
-       INT i;
+       if (Conf_NoZeroConf)
+               return;
 
        /* 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 );
-               return FALSE;
+               return false;
        }
        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 );
-               return FALSE;
+               My_Rendezvous[i].Desc[0] = '\0';
+               return false;
        }
        
        /* Get and save the corresponding Mach Port */
@@ -117,28 +180,39 @@ GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR *Type, UINT Port )
                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;
-               return FALSE;
+               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;
+       return true;
 } /* Rendezvous_Register */
 
 
-GLOBAL BOOLEAN Rendezvous_Unregister( CHAR *Name )
+GLOBAL bool Rendezvous_Unregister( char *Name )
 {
        /* Unregister service from rendezvous */
 
-       INT i;
-       BOOLEAN ok;
+       int i;
+       bool ok;
 
-       ok = FALSE;
+       ok = false;
        for( i = 0; i < MAX_RENDEZVOUS; i++ )
        {
                if( strcmp( Name, My_Rendezvous[i].Desc ) == 0 )
                {
                        Unregister( i );
-                       ok = TRUE;
+                       ok = true;
                }
        }
 
@@ -146,26 +220,27 @@ GLOBAL BOOLEAN Rendezvous_Unregister( CHAR *Name )
 } /* Rendezvous_Unregister */
 
 
-GLOBAL VOID Rendezvous_UnregisterListeners( VOID )
+GLOBAL void Rendezvous_UnregisterListeners( void )
 {
        /* Unregister all our listening sockets from Rendezvous */
 
-       INT i;
+       int i;
 
        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 */
 
 
-GLOBAL VOID Rendezvous_Handler( VOID )
+GLOBAL void Rendezvous_Handler( void )
 {
        /* Handle all Rendezvous stuff; this function must be called
         * periodically from the run loop of the main program */
 
-       INT i;
-       CHAR buffer[MAX_MACH_MSG_SIZE];
+#ifdef APPLE
+       int i;
+       char buffer[MAX_MACH_MSG_SIZE];
        mach_msg_return_t result;
        mach_msg_header_t *msg;
 
@@ -180,20 +255,53 @@ GLOBAL VOID Rendezvous_Handler( VOID )
                /* Handle message */
                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
+               else if( result != MACH_RCV_TIMED_OUT ) Log( LOG_DEBUG, "mach_msg(): %ld", (long)result );
+#endif /* Debug */
        }
+#endif /* Apple */
+
+#ifdef HOWL
+       sw_ulong msecs = 10;
+       sw_salt_step( My_Salt, &msecs );
+#endif
 } /* Rendezvous_Handler */
 
 
-LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context )
+static void Unregister( int Idx )
 {
-       CHAR txt[50];
+       /* 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
+
+
+static 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;
        }
 
@@ -206,24 +314,59 @@ LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrC
                        strcpy( txt, "name conflict!" );
                        break;
                default:
-                       sprintf( txt, "error code %ld!", (LONG)ErrCode );
+                       snprintf(txt, sizeof 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
+
+
+static 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:
+                       snprintf(txt, sizeof 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 */
+
+
+#endif /* Howl */
 
 
-#endif /* RENDEZVOUS */
+#endif /* ZEROCONF */
 
 
 /* -eof- */