123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- /*
- * ngIRCd -- The Next Generation IRC Daemon
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * Please read the file COPYING, README and AUTHORS for more information.
- *
- * Rendezvous service registration.
- *
- * Supported APIs are:
- * - Apple Mac OS X
- * - Howl
- */
- #include "portab.h"
- #ifdef ZEROCONF
- static char UNUSED id[] = "$Id: rendezvous.c,v 1.8 2006/05/10 21:24:01 alex Exp $";
- #include "imp.h"
- #include <assert.h>
- #include <stdio.h>
- #include <string.h>
- #ifdef HAVE_MACH_PORT_H
- #include "mach/port.h"
- #include "mach/message.h"
- #endif
- #ifdef HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H
- #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
- #endif
- #ifdef HAVE_RENDEZVOUS_RENDEZVOUS_H
- #include <rendezvous/rendezvous.h>
- #endif
- #include "defines.h"
- #include "log.h"
- #include "exp.h"
- #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;
- #endif
- #ifdef HOWL
- sw_discovery_oid Id;
- #endif
- } SERVICE;
- static SERVICE My_Rendezvous[MAX_RENDEZVOUS];
- static void Unregister( int Idx );
- /* -- Apple API -- */
- #ifdef APPLE
- #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 );
- #endif /* Howl */
- GLOBAL void Rendezvous_Init( void )
- {
- /* Initialize structures */
- int i;
- #ifdef HOWL
- if( sw_discovery_init( &My_Discovery_Session ) != SW_OKAY )
- {
- 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 )
- {
- /* Clean up & exit module */
- int i;
- for( i = 0; i < MAX_RENDEZVOUS; i++ )
- {
- if( My_Rendezvous[i].Desc[0] ) Unregister( i );
- }
- #ifdef HOWL
- sw_discovery_fina( My_Discovery_Session );
- #endif
- } /* Rendezvous_Exit */
- GLOBAL bool Rendezvous_Register( char *Name, char *Type, UINT16 Port )
- {
- /* Register new service */
- int i;
- /* Search free port structure */
- 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;
- }
- 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] );
- 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;
- }
-
- /* Get and save the corresponding Mach Port */
- My_Rendezvous[i].Mach_Port = DNSServiceDiscoveryMachPort( My_Rendezvous[i].Discovery_Ref );
- if( ! My_Rendezvous[i].Mach_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;
- 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 */
- GLOBAL bool Rendezvous_Unregister( char *Name )
- {
- /* Unregister service from rendezvous */
- int i;
- bool ok;
- ok = false;
- for( i = 0; i < MAX_RENDEZVOUS; i++ )
- {
- if( strcmp( Name, My_Rendezvous[i].Desc ) == 0 )
- {
- Unregister( i );
- ok = true;
- }
- }
- return ok;
- } /* Rendezvous_Unregister */
- GLOBAL void Rendezvous_UnregisterListeners( void )
- {
- /* Unregister all our listening sockets from Rendezvous */
- int i;
- for( i = 0; i < MAX_RENDEZVOUS; i++ )
- {
- if( My_Rendezvous[i].Desc[0] ) Unregister( i );
- }
- } /* Rendezvous_UnregisterListeners */
- 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;
- mach_msg_header_t *msg;
- for( i = 0; i < MAX_RENDEZVOUS; i++ )
- {
- if( ! My_Rendezvous[i].Discovery_Ref ) continue;
- /* Read message from Mach Port */
- msg = (mach_msg_header_t *)buffer;
- result = mach_msg( msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, MAX_MACH_MSG_SIZE, My_Rendezvous[i].Mach_Port, 1, 0 );
- /* 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 /* Debug */
- }
- #endif /* Apple */
- #ifdef HOWL
- sw_ulong msecs = 10;
- sw_salt_step( My_Salt, &msecs );
- #endif
- } /* Rendezvous_Handler */
- static 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
- 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.", s->Desc );
- return;
- }
- switch( ErrCode )
- {
- case kDNSServiceDiscoveryAlreadyRegistered:
- strcpy( txt, "name already registered!" );
- break;
- case kDNSServiceDiscoveryNameConflict:
- strcpy( txt, "name conflict!" );
- break;
- default:
- snprintf(txt, sizeof txt, "error code %ld!",
- (long)ErrCode);
- }
- Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", s->Desc, txt );
- s->Desc[0] = '\0';
- } /* Registration_Reply_Handler */
- #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 )
- {
- SERVICE *s = (SERVICE *)Extra;
- char txt[50];
- 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 /* ZEROCONF */
- /* -eof- */
|