gml_ServiceDiscovery.h

Go to the documentation of this file.
00001 /** @file gml_ServiceDiscovery.h
00002  * 
00003  *     Object interface to the DNSServiceDiscovery API.
00004  * 
00005  *     Note that registered callbacks aren't passed result data;
00006  *     they should instead fetch it using the GetAnswer() methods of the
00007  *     various classes.
00008  * 
00009  *     Classes defined: gml_TSDBrowser, gml_TSDRegistrator, gml_TSDResolver.
00010  * 
00011  *   Copyright (c) 2004 CLIPS-IMAG
00012  * 
00013  *   See the file "gml_LicenseTerms.txt" for information on usage and redistribution
00014  *   of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00015  * 
00016  */
00017 #ifndef __GML_SERVICE_DISCOVERY__
00018 #define __GML_SERVICE_DISCOVERY__
00019 
00020 #include <assert.h>
00021 #include <stdint.h>
00022 
00023 #include "gml/base/gml_Array.h"
00024 #include "gml/base/gml_Callback.h"
00025 #include "gml/base/gml_Queue.h"
00026 #include "gml/base/gml_Thread.h"
00027 
00028 
00029 
00030 // as per DNS-SD draft:
00031 #define GML_MAX_TXT_LENGTH    8800
00032 #define GML_MAX_NAME_LENGTH   62
00033 #define GML_MAX_HOST_LENGTH   256
00034 #define GML_MAX_TYPE_LENGTH   62
00035 
00036 
00037 // forward declaration of dns-sd structures
00038 
00039 typedef struct _DNSServiceRef_t *DNSServiceRef;
00040 typedef uint32_t DNSServiceFlags;
00041 typedef int32_t  DNSServiceErrorType;
00042 
00043 
00044 
00045 ///////////////////////////////////////////////////////////////////////////////
00046 #pragma mark -
00047 #pragma mark General tools for DNS-SD connections
00048 
00049 
00050 
00051 
00052 
00053 
00054 /// gml_TSDMetaDataEntry --
00055 ///
00056 ///   A field of a TXT record.
00057 
00058 struct gml_TSDMetaDataEntry
00059 {
00060   gml_TSDMetaDataEntry ()
00061   {
00062     gml_Zero (fKey);
00063     gml_Zero (fValue);
00064     fHasValue = false;
00065   }
00066 
00067   gml_TSDMetaDataEntry (char* key, char* value = (char*)NULL)
00068   {
00069     assert (strlen (key) < 256);
00070     strncpy (fKey, key, 256);
00071     
00072     if (value != (char*)NULL) {
00073       strncpy (fValue, value, 256);
00074       fHasValue = true;
00075     } else {
00076       fHasValue = false;
00077     }
00078   }
00079 
00080   char fKey   [256];      ///< the field name or key
00081   char fValue [256];      ///< the corresponding value (can be empty)
00082   bool fHasValue;         ///< wether the field has a value (or is only a key)
00083 };
00084 
00085 
00086 
00087 /// gml_TSDMetaData --
00088 ///
00089 ///   Represent a TXT record as an array of entries.
00090 
00091 class gml_TSDMetaData : public gml_TArray<gml_TSDMetaDataEntry>
00092 {
00093 public:
00094 
00095   /// Init --
00096   ///
00097   /// Setup a new TXT record.
00098 
00099   gml_TError Init ();
00100   
00101   /// Export --
00102   ///
00103   ///   Convert the metadata array into a pascal-style array of strings.
00104 
00105   void Export (unsigned &bytes, unsigned char* record);
00106 
00107   /// Import --
00108   ///
00109   ///   Flush the array and fill it with the supplied pascal-style array.
00110 
00111   gml_TError Import (unsigned bytes, unsigned char const* record);
00112 };
00113 
00114 
00115 
00116 
00117 /// gml_TSDConnection --
00118 ///
00119 ///   Encapsulate a connection to the DNS Service Discovery daemon.
00120 ///   This class cannot be instantiated.
00121 
00122 class gml_TSDConnection
00123 {
00124   public:
00125 
00126     /// Delete --
00127     ///
00128     ///   Terminate a SD connection, given it's ID number.
00129 
00130     static void Delete (int id) ;
00131 
00132 
00133     /// Dispose --
00134     ///
00135     ///   Terminate the SD connection.
00136 
00137     virtual void Dispose ();
00138     
00139     virtual ~gml_TSDConnection () {}
00140     
00141 
00142     /// Identity --
00143     ///
00144     ///   Return the ID number of this SD connection.
00145 
00146     virtual int Identity () {
00147       return fInstanceID;
00148     }
00149     
00150 
00151   protected:
00152 
00153     /// Init --
00154     ///
00155     ///   Setup private data.
00156 
00157     gml_TError Init ();
00158 
00159     /// Start --
00160     ///
00161     ///   Register this SD connection.
00162     ///   Setup a watcher thread so that <callback> is called with
00163     ///   parameter <userData> whenever a SD event occurs on <sdRef>.
00164 
00165     gml_TError Start (DNSServiceRef sdRef, gml_TCallback callback, gml_TPointer userData);
00166 
00167 
00168     /// Notify --
00169     ///
00170     ///   Execute the registered callback, with parameter <err>.
00171 
00172     virtual void Notify (gml_TError err = gml_cNoError);
00173 
00174 
00175   private:
00176 
00177     /// SocketNotifierGeneric --
00178     ///
00179     ///   Generic entry point for SD connection watcher threads.
00180 
00181     static
00182     void SocketNotifierGeneric (gml_TThreadId tid, void* clientdata);
00183 
00184 
00185     /// SocketNotifier --
00186     ///
00187     ///   Entry point for SD connection watcher threads.
00188 
00189     void SocketNotifier ();
00190 
00191 
00192   private:
00193     
00194     DNSServiceRef         fSdRef;             ///< connection to mDNSd
00195     int                   fInstanceID;        ///< unique identifier for a SD connection
00196     gml_TCallback         fCallback;          ///< registered callback function
00197     gml_TPointer          fUserData;          ///< registered callback argument
00198     int                   fSelectThreadRun;   ///< flag controlling the notification thread
00199     gml_TThreadId         fSelectThread;      ///< identifier of the notification thread
00200     static int            fInstanceCounter;   ///< total number of SD connections since startup
00201     static gml_TList*     fInstances;         ///< current list of SD connections
00202 };
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 ///////////////////////////////////////////////////////////////////////////////
00212 #pragma mark -
00213 #pragma mark Service browsing
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 /// gml_TSDBrowser --
00222 ///
00223 ///   Perform discovery of available network services.
00224 
00225 class gml_TSDBrowser : public gml_TSDConnection
00226 {
00227   public:
00228 
00229 
00230     /// Init --
00231     ///
00232     ///   Setup a new browser.
00233 
00234     gml_TError Init (
00235       gml_TCallback callback,                     ///< function to be called on browser events
00236       gml_TPointer  userData,                     ///< parameter passed to <callback>
00237       const char*   regType,                      ///< service type browsed for, e.g. "_http._tcp"
00238       UInt32        interfaceIndex = (UInt32)0,   ///< number of browsing inferface, -1 for local search only
00239       const char*   nameGlob       = (char*)NULL  ///< glob filtering pattern for service names
00240     );
00241 
00242 
00243     /// Dispose --
00244     ///
00245     ///   Stop browsing.
00246 
00247     void Dispose ();
00248 
00249 
00250     /// Event --
00251     ///
00252     ///   Representation of browser events.
00253 
00254     struct Event {
00255       gml_TBoolean    fAdded;                             ///< true iff the service appeared
00256       char            fName     [GML_MAX_NAME_LENGTH+1];  ///< service (unique) name
00257       char            fRegType  [GML_MAX_NAME_LENGTH+1];  ///< type of discovered service
00258       char            fDomain   [GML_MAX_HOST_LENGTH+1];  ///< service domain
00259     };
00260 
00261 
00262     /// GetAnswer --
00263     ///
00264     ///   Return in <event> the oldest available browsing event, and remove it
00265     ///   from the event queue; if no event is available, return
00266     ///    <gml_TQueue_Base::sErrorQueueEmpty>.
00267 
00268     gml_TError GetAnswer (Event &event);
00269 
00270 
00271   private:
00272 
00273 
00274     /// HandlerEvent --
00275     ///
00276     ///   Called by <DNSServiceProcessResult> on incoming events.
00277     ///   @see <gml_TSDConnection::SocketNotifier>.
00278 
00279     static
00280     void HandlerEvent (
00281         DNSServiceRef                       /*sdRef*/,
00282         DNSServiceFlags                     flags,
00283         uint32_t                            /*interfaceIndex*/,
00284         DNSServiceErrorType                 errorCode,
00285         const char                          *serviceName,  
00286         const char                          *regType,    
00287         const char                          *eventDomain,  
00288         void                                *context
00289     );
00290 
00291 
00292   private:
00293 
00294     gml_TQueue<Event>*  fEvents;                            ///< unprocessed browsing events
00295     char                fNameGlob [GML_MAX_NAME_LENGTH+1];  ///< filtering glob pattern
00296 };
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 ///////////////////////////////////////////////////////////////////////////////
00307 #pragma mark -
00308 #pragma mark Service registration
00309 
00310 
00311 
00312 
00313 /// gml_TSDRegistrator --
00314 ///
00315 ///   Register a discoverable service.
00316 
00317 class gml_TSDRegistrator: public gml_TSDConnection
00318 {
00319 public:
00320 
00321 
00322     /// Init --
00323     ///
00324     ///   Setup a new registrator.
00325 
00326     gml_TError Init (
00327       gml_TCallback            callback,                      ///< function to be called when registration completes
00328       gml_TPointer             userData,                      ///< parameter to <callback>
00329       const char*              regType,                       ///< type of service
00330       UInt16                   port,                          ///< port associated with the service
00331       const char*              name            = (char*)NULL, ///< service name (a sensible default may be chosen)
00332       UInt32                   interfaceIndex  = (UInt32)0,   ///< registration interface, -1 for local only
00333       gml_TSDMetaData*         metaData        = NULL
00334     );
00335 
00336 
00337 
00338     /// GetAnswer --
00339     ///
00340     ///   Return the registration results.
00341     ///   In particular, <name> and <domain> may have not been provided at <Init>.
00342 
00343     void GetAnswer (char** name, char** regtype, char** domain);
00344 
00345 
00346   private:
00347 
00348 
00349     /// HandlerEvent --
00350     ///
00351     ///   Called by <DNSServiceProcessResult> on incoming events.
00352     ///   @see <gml_TSDConnection::SocketNotifier>.
00353 
00354     static
00355     void HandlerEvent (
00356         DNSServiceRef       /*sdRef*/,
00357         DNSServiceFlags     /*flags*/,
00358         DNSServiceErrorType errorCode,
00359         const char*         name,
00360         const char*         regType,
00361         const char*         domain,
00362         void*               context
00363     );
00364 
00365   private:
00366     char fName    [GML_MAX_NAME_LENGTH+1]; ///< registered service name
00367     char fRegType [GML_MAX_TYPE_LENGTH+1]; ///< registered service type
00368     char fDomain  [GML_MAX_HOST_LENGTH+1]; ///< registered service domain
00369 };
00370 
00371 
00372 
00373 
00374 
00375 
00376 ///////////////////////////////////////////////////////////////////////////////
00377 #pragma mark -
00378 #pragma mark Service name resolution
00379 
00380 
00381 ///
00382 /// gml_TSDResolver --
00383 ///
00384 ///   Determine the host, port and metadata of a named service.
00385 ///
00386 class gml_TSDResolver : public gml_TSDConnection
00387 {
00388   public:
00389 
00390 
00391     /// Init --
00392     ///
00393     ///   Setup a new SD resolver.
00394 
00395     gml_TError Init (
00396       gml_TCallback            callback,                      ///< function to be called when resolution completes
00397       gml_TPointer             userData,                      ///< parameter to <callback>
00398       const char*              name,                          ///< name of service to resolve
00399       const char*              regType,                       ///< type of service to resolve
00400       const char*              domain          = "local.",    ///< domain where to resolve
00401       UInt32                   interfaceIndex  = (UInt32)0    ///< resolution interface, -1 for local only
00402     );
00403 
00404 
00405     /// GetAnswer --
00406     ///
00407     ///   Return information about the resolved service.
00408 
00409     void GetAnswer (char** fullname, char** hostname, UInt16* port, gml_TSDMetaData** data);
00410 
00411 
00412   private:
00413 
00414 
00415     /// HandlerEvent --
00416     ///
00417     ///   Called by <DNSServiceProcessResult> on incoming events.
00418     ///   @see <gml_TSDConnection::SocketNotifier>.
00419 
00420     static
00421     void HandlerEvent (
00422         DNSServiceRef       /*sdRef*/,
00423         DNSServiceFlags     /*flags*/,
00424         uint32_t            /*interfaceIndex*/,
00425         DNSServiceErrorType errorCode,
00426         const char*         fullname,
00427         const char*         hosttarget,
00428         uint16_t            port,
00429         uint16_t            txtLen,
00430         void* txtRecord,
00431         void*               context
00432     );
00433 
00434 
00435 
00436   public:
00437     char              fFullName[GML_MAX_HOST_LENGTH+1];
00438     char              fHostName[GML_MAX_HOST_LENGTH+1];
00439     UInt16            fPort;
00440     gml_TSDMetaData*  fMetaData;
00441 
00442 };
00443 
00444 
00445 
00446 
00447 #endif /* __GML_SERVICE_DISCOVERY__ */
00448 
00449 
Generated on Tue Jun 12 14:03:27 2007 for gml by Doxygen 1.5.2.