2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
11 * Rendezvous service registration (using Mach Ports, e.g. Mac OS X)
20 static char UNUSED id[] = "$Id: rendezvous.c,v 1.1 2003/02/23 12:02:26 alex Exp $";
28 #ifdef HAVE_MACH_PORT_H
29 #include "mach/port.h"
30 #include "mach/message.h"
33 #ifdef HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H
34 #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
41 #include "rendezvous.h"
44 typedef struct _service
46 dns_service_discovery_ref Discovery_Ref;
47 mach_port_t Mach_Port;
48 CHAR Desc[CLIENT_ID_LEN];
52 LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context );
53 LOCAL VOID Unregister( INT Idx );
56 #define MAX_RENDEZVOUS 1000
57 #define MAX_MACH_MSG_SIZE 512
60 LOCAL SERVICE My_Rendezvous[MAX_RENDEZVOUS];
63 GLOBAL VOID Rendezvous_Init( VOID )
65 /* Initialize structures */
69 for( i = 0; i < MAX_RENDEZVOUS; i++ )
71 My_Rendezvous[i].Discovery_Ref = 0;
72 My_Rendezvous[i].Mach_Port = 0;
74 } /* Rendezvous_Init */
77 GLOBAL VOID Rendezvous_Exit( VOID )
79 /* Clean up & exit module */
83 for( i = 0; i < MAX_RENDEZVOUS; i++ )
85 if( My_Rendezvous[i].Discovery_Ref ) Unregister( i );
87 } /* Rendezvous_Exit */
90 GLOBAL BOOLEAN Rendezvous_Register( CHAR *Name, CHAR *Type, UINT Port )
92 /* Register new service */
96 /* Search free port structure */
97 for( i = 0; i < MAX_RENDEZVOUS; i++ ) if( ! My_Rendezvous[i].Discovery_Ref ) break;
98 if( i >= MAX_RENDEZVOUS )
100 Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: limit (%d) reached!", Name, MAX_RENDEZVOUS );
103 strlcpy( My_Rendezvous[i].Desc, Name, sizeof( My_Rendezvous[i].Desc ));
105 /* Register new service */
106 My_Rendezvous[i].Discovery_Ref = DNSServiceRegistrationCreate( Name, Type, "", htonl( Port ), "", Registration_Reply_Handler, My_Rendezvous[i].Desc );
107 if( ! My_Rendezvous[i].Discovery_Ref )
109 Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: can't register service!", My_Rendezvous[i].Desc );
113 /* Get and save the corresponding Mach Port */
114 My_Rendezvous[i].Mach_Port = DNSServiceDiscoveryMachPort( My_Rendezvous[i].Discovery_Ref );
115 if( ! My_Rendezvous[i].Mach_Port )
117 Log( LOG_ERR, "Can't register \"%s\" with Rendezvous: got no Mach Port!", My_Rendezvous[i].Desc );
118 /* Here we actually leek a descriptor :-( */
119 My_Rendezvous[i].Discovery_Ref = 0;
123 Log( LOG_DEBUG, "Rendezvous: Registering \"%s\" ...", My_Rendezvous[i].Desc );
125 } /* Rendezvous_Register */
128 GLOBAL BOOLEAN Rendezvous_Unregister( CHAR *Name )
130 /* Unregister service from rendezvous */
136 for( i = 0; i < MAX_RENDEZVOUS; i++ )
138 if( strcmp( Name, My_Rendezvous[i].Desc ) == 0 )
146 } /* Rendezvous_Unregister */
149 GLOBAL VOID Rendezvous_UnregisterListeners( VOID )
151 /* Unregister all our listening sockets from Rendezvous */
155 for( i = 0; i < MAX_RENDEZVOUS; i++ )
157 if( strchr( My_Rendezvous[i].Desc, '.' )) Unregister( i );
159 } /* Rendezvous_UnregisterListeners */
162 GLOBAL VOID Rendezvous_Handler( VOID )
164 /* Handle all Rendezvous stuff; this function must be called
165 * periodically from the run loop of the main program */
168 CHAR buffer[MAX_MACH_MSG_SIZE];
169 mach_msg_return_t result;
170 mach_msg_header_t *msg;
172 for( i = 0; i < MAX_RENDEZVOUS; i++ )
174 if( ! My_Rendezvous[i].Discovery_Ref ) continue;
176 /* Read message from Mach Port */
177 msg = (mach_msg_header_t *)buffer;
178 result = mach_msg( msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, MAX_MACH_MSG_SIZE, My_Rendezvous[i].Mach_Port, 1, 0 );
181 if( result == MACH_MSG_SUCCESS ) DNSServiceDiscovery_handleReply( msg );
183 else if( result != MACH_RCV_TIMED_OUT ) Log( LOG_DEBUG, "mach_msg(): %ld", (LONG)result );
186 } /* Rendezvous_Handler */
189 LOCAL VOID Registration_Reply_Handler( DNSServiceRegistrationReplyErrorType ErrCode, VOID *Context )
193 if( ErrCode == kDNSServiceDiscoveryNoError )
196 Log( LOG_INFO, "Successfully registered \"%s\" with Rendezvous.", Context ? Context : "NULL" );
202 case kDNSServiceDiscoveryAlreadyRegistered:
203 strcpy( txt, "name already registered!" );
205 case kDNSServiceDiscoveryNameConflict:
206 strcpy( txt, "name conflict!" );
209 sprintf( txt, "error code %ld!", (LONG)ErrCode );
212 Log( LOG_INFO, "Can't register \"%s\" with Rendezvous: %s", Context ? Context : "NULL", txt );
213 } /* Registration_Reply_Handler */
216 LOCAL VOID Unregister( INT Idx )
218 /* Unregister service */
220 DNSServiceDiscoveryDeallocate( My_Rendezvous[Idx].Discovery_Ref );
221 Log( LOG_INFO, "Unregistered \"%s\" from Rendezvous.", My_Rendezvous[Idx].Desc );
222 My_Rendezvous[Idx].Discovery_Ref = 0;
226 #endif /* RENDEZVOUS */