/usr/include/gloox/linklocalmanager.h is in libgloox-dev 1.0.9-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | /*
Copyright (c) 2012-2013 by Jakob Schroeter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#ifndef LINKLOCALMANAGER_H___
#define LINKLOCALMANAGER_H___
#include "config.h"
#ifdef HAVE_MDNS
#include "linklocal.h"
#include "macros.h"
#include "gloox.h"
#include "util.h"
#include "logsink.h"
#include "connectiontcpserver.h"
#include "mutex.h"
#include "jid.h"
#include <string>
#include <dns_sd.h>
namespace gloox
{
class ConnectionHandler;
class ConnectionTCPClient;
namespace LinkLocal
{
class Handler;
/**
* @brief This is a manager for server-less messaging (@xep{0174}).
*
* Enable compilation of this code with the @c \-\-enable-mdns switch to @c configure, or add
* @c \#define @c HAVE_MDNS to your platform's @c config.h. @c dns_sd.h, @c libdns_sd.so, as well
* as the @c mdnsd daemon from Apple's bonjour distribution are required. The @c mdnsd daemon has
* to be running on the local host.
*
* ### Browsing the local network for XMPP services
*
* You can use the Manager to browse the local network for XMPP services.
* First, create a new instance, register a LinkLocal::Handler, and call startBrowsing().
* @code
* m_mdns = new LinkLocal::Manager( ... );
* m_mdns->registerLinkLocalHandler( yourHandler );
* m_mdns->startBrowsing();
* @endcode
*
* Then you will need to call @c recv() periodcally. The handler will then receive lists of available
* or removed services. Check the @c flag member of the Service struct.
*
* @code
* void MyClass::handleBrowseReply( const Service& service )
* {
* LinkLocal::ServiceList::const_iterator it = services.begin();
* for( ; it != services.end(); ++it )
* {
* if( (*it).flag == LinkLocal::AddService )
* {
* // new service
* }
* else
* {
* // service removed
* }
* }
* }
* @endcode
*
* @note Note that your own service may show up in the list, too.
*
* ### Connecting to an XMPP service
*
* Using the info from the Service struct you can initiate a connection to the remote entity.
* First, create a new instance of LinkLocal::Client and register some basic handlers like you
* would with a normal gloox::Client:
*
* @code
* LinkLocal::Client c( JID( "romeo@montague.net" ) );
* c.logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this ); // optional
* c.registerConnectionListener( yourConnectionListener );
* @endcode
*
* Then call @link gloox::LinkLocal::Client::connect( const std::string&, const std::string&, const std::string&, int ) connect() @endlink
* and pass the paramters from the Service struct that you received in handleBrowseReply().
*
* @code
* c.connect( "juliet@laptop", "_presence._tcp", ".local", 4 ); // don't use literal values
* @endcode
*
* Put your LinkLocal::Client instance in your event loop (or in a separate thread) and call
* @link gloox::LinkLocal::Client::recv() recv() @endlink periodically.
*
* ### Advertising an XMPP service on the local network
*
* To advertise your own XMPP service you can (re-)use the same Manager instance from 'browsing the local network'
* above.
*
* You can publish some basic info about your service in a DNS TXT record. The Manager offers the addTXTData() function
* for that. See http://xmpp.org/registrar/linklocal.html for a list of official parameters.
*
* @code
* m_mdns->addTXTData("nick","July");
* m_mdns->addTXTData("1st","Juliet");
* m_mdns->addTXTData("last","Capulet");
* m_mdns->addTXTData("msg","Hanging out");
* m_mdns->addTXTData("jid","julia@capulet.com");
* m_mdns->addTXTData("status","avail");
* @endcode
*
* Then, to start publishing the availability of your service as well as the TXT record with the additional info
* you just call @c registerService().
*
* @code
* m_mdns->registerService();
* @endcode
*
* Other entities on the network will now be informed about the availability of your service.
*
* ### Listening for incoming connections
*
* The second argument to Manager's constructor is a ConnectionHandler-derived class that
* will receive incoming connections.
*
* When registerService() gets called, the Manager will also start a local server that will
* accept incoming connections. By default, it will listen on port 5562.
*
* In @link gloox::ConnectionHandler::handleIncomingConnection() handleIncomingConnection() @endlink
* you should create a new LinkLocal::Client and register some basic handlers:
*
* @code
* LinkLocal::Client c( JID( "romeo@desktop" ) );
* c.logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this );
* c.registerMessageHandler( this );
* c.registerConnectionListener( this );
* @endcode
*
* Finally you have to attach the incoming connection to the Client instance, and call connect().
*
* @code
* connection->registerConnectionDataHandler( &c );
* c.setConnectionImpl( connection );
* c.connect();
* @endcode
*
* Add the Client to your event loop to call recv() periodically.
*
* @see @c linklocal_example.cpp in @c src/examples/ for a (very) simple implementation of a bot
* handling both incoming and outgoing connections.
*
* @author Jakob Schroeter <js@camaya.net>
* @since 1.0.x
*/
class GLOOX_API Manager
{
public:
/**
* Creates a new Link-local Manager instance. You can call @c registerService() and/or @c startBrowsing()
* immediately on a new Manager object, it will use sane defaults.
* @param user The username to advertise, preferably (as per @xep{0174}) the locally
* logged-in user. This is just the local part of the local JID.
* @param connHandler A pointer to a ConnectionHandler that will receive incoming connections.
* @param logInstance The log target. Obtain it from ClientBase::logInstance().
*/
Manager( const std::string& user, ConnectionHandler* connHandler, const LogSink &logInstance );
/**
* Virtual destructor.
* @note @c deregisterService() and @c stopBrowsing() will be called automatically if necessary.
*/
virtual ~Manager();
/**
* Lets you add additional data to the published TXT record.
* @note The @c txtvers=1 parameter is included by default and cannot be changed.
* @param key The key of a key=value parameter pair. Must be non-empty. If the given key
* has been set before, its value will be overwritten by the new value.
* @param value The value of a @c key=value parameter pair. Must be non-empty.
* @note If either parameter is empty, this function is a NOOP.
* @note The additional data will not be automatically published if you have already called
* @c registerService(). You will have to call @c registerService() again to update the
* TXT record.
*/
void addTXTData( const std::string& key, const std::string& value );
/**
* Lets you remove TXT record data by key.
* @note The @c txtvers=1 parameter is included by default and cannot be removed.
* @param key The key of the @c key=value parameter pair that should be removed. Must be non-empty.
* @note A published TXT record will not be automatically updated if you have already called
* @c registerService(). You will have to call @c registerService() again to update the TXT record.
*/
void removeTXTData( const std::string& key );
/**
* Starts advertising link-local messaging capabilities by publishing a number of DNS records,
* as per @xep{0174}.
* You can call this function again to publish any values you updated after the first call.
*/
void registerService();
/**
* Removes the published DNS records and thereby stops advertising link-local messaging
* capabilities.
*/
void deregisterService();
/**
* Lets you specify a new username.
* @param user The new username.
* @note The new username will not be automatically advertised if you have already called
* @c registerService(). You will have to call @c registerService() again to update the username.
*/
void setUser( const std::string& user ) { m_user = user; }
/**
* Lets you specify an alternate host name to advertise. By default the local machine's hostname
* as returned by @c gethostname() will be used.
* @param host The hostname to use.
* @note The new hostname will not be automatically advertised if you have already called
* @c registerService(). You will have to call @c registerService() again to update the hostname.
*/
void setHost( const std::string& host ) { m_host = host; }
/**
* This function lets you set an alternate browse domain. The default domain should work in most cases.
* @param domain The browse domain to set.
* @note The new domain will not be automatically used if you have already called
* @c registerService(). You will have to call @c registerService() again to update the domain.
* The same applies to @c startBrowsing().
*/
void setDomain( const std::string& domain ) { m_domain = domain; }
/**
* Lets you specifiy a port to listen on for incoming server-less XMPP connections. Default
* for this implementation is port 5562, but any unused port can be used.
* @note In addition to the SRV record, the port will also be published in the TXT record
* automaticlly, you do not have to add it manually. That is, you should not call
* @c addTXTData() with a key of @c "port.p2pj".
* @param port The port to use.
* @note The new port will not be automatically advertised if you have already called
* @c registerService(). You will have to call @c registerService() again to update the port.
*/
void setPort( const int port ) { m_port = port; addTXTData( "port.p2pj", util::int2string( m_port ) ); }
/**
* This function can be used to set a non-default interface. Use @c if_nametoindex() to
* find the index for a specific named device.
* By default DNS records will be broadcast on all available interfaces, and all available
* interfaces will be used or browsing services.
* @param iface The interface to use. If you set an interface here, and want to change it
* back to 'any', use @b 0. Use @b -1 to broadcast only on the local machine.
* @note The new interface will not be automatically used if you have already called
* @c registerService(). You will have to call @c registerService() again to use the new
* interface. The same applies to @c startBrowsing().
*/
void setInterface( unsigned iface ) { m_interface = iface; }
/**
* Starts looking for other entities of type @c _presence. You have to set a handler for
* results using @c registerLinkLocalHandler() before calling this function.
* You can call this function again to re-start browsing with updated parameters.
* @return Returns @b true if browsing could be started successfully, @b false otherwise.
*/
bool startBrowsing();
/**
* Stops the browsing.
*/
void stopBrowsing();
/**
* Exposes the socket used for browsing so you can have it checked in your own event loop,
* if desired. If your event loop signals new data on the socket, you should NOT
* try to read from it directly. Instead you should call @c recv().
* As an alternative to using the raw socket you could also put the Manager in a
* separate thread and call @c recv() repeatedly, or achieve this in any other way.
*/
int socket() const { return m_browseFd; }
/**
* Checks once for new data on the socket used for browsing.
* @param timeout The timeout for @c select() in microseconds. Use @b -1 if blocking behavior
* is acceptable.
*/
void recv( int timeout );
/**
* Registers a handler that will be notfied about entities found on the network that match
* the given browse criteria.
* @param handler The handler to register.
*/
void registerLinkLocalHandler( Handler* handler ) { m_linkLocalHandler = handler; }
// /**
// *
// */
// static const StringMap decodeTXT( const std::string& txt );
private:
static void handleBrowseReply( DNSServiceRef sdRef, DNSServiceFlags flags, unsigned interfaceIndex,
DNSServiceErrorType errorCode, const char* serviceName, const char* regtype,
const char* replyDomain, void* context );
void handleBrowse( Flag flag, const std::string& service, const std::string& regtype, const std::string& domain, int interface, bool moreComing );
typedef std::list<ConnectionTCPClient*> ConnectionList;
typedef std::map<ConnectionTCPClient*, const JID> ConnectionMap;
DNSServiceRef m_publishRef;
DNSServiceRef m_browseRef;
ServiceList m_tmpServices;
// ServiceList m_services;
std::string m_user;
std::string m_host;
std::string m_domain;
unsigned m_interface;
int m_port;
const LogSink& m_logInstance;
int m_browseFd;
StringMap m_txtData;
ConnectionTCPServer m_server;
Handler* m_linkLocalHandler;
ConnectionHandler* m_connectionHandler;
};
}
}
#endif // HAVE_MDNS
#endif // LINKLOCALMANAGER_H___
|