00001 /* $Id: servicedirectory.hh,v 1.20 2003/07/05 04:07:16 tetron Exp $ 00002 00003 Copyright (C) 2002 Peter Amstutz <tetron@interreality.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 */ 00020 00021 #ifndef _SERVICEDIRECTORY_HH_ 00022 #define _SERVICEDIRECTORY_HH_ 00023 00024 #include <string> 00025 #include <set> 00026 #include <deque> 00027 #include <map> 00028 00029 /** Library for Service Discovery */ 00030 namespace LSD { 00031 00032 struct Service 00033 { 00034 public: 00035 std::set<std::string> types; 00036 std::string title; 00037 std::string description; 00038 std::string url; 00039 Service() {} 00040 Service(const std::set<std::string>& ty, const std::string& ti, const 00041 std::string& d, const std::string& u) : 00042 types(ty), title(ti), description(d), url(u) {} 00043 }; 00044 00045 00046 00047 class ServiceAdvertismentListener 00048 { 00049 public: 00050 virtual ~ServiceAdvertismentListener() { } 00051 virtual void notifyNewService(int id, const Service& s) = 0; 00052 }; 00053 00054 /** This class represents a service directory. Service directories can query and 00055 * advertise services which are registered locally, or remotely, via UDP 00056 * broadcast or point-to-point TCP messages. 00057 * A service is identified by human readable title and description, a list 00058 * of type strings, and a URL. 00059 * @todo add optional relaying of all local traffic to remote 00060 * tcp relays. 00061 */ 00062 class ServiceDirectory 00063 { 00064 private: 00065 std::set<Service*> services; 00066 int udp_fd; // incoming and outgoing broadcasts 00067 std::map< std::pair<char*, int>, int > tcp_relays; // outgoing relays 00068 int tcp_fd; // listening 00069 std::deque<int> incoming_tcp_fds; // incoming tpc sockets 00070 bool relay_tcp_local; // if true, relay incoming messages from the tcp sockets to the broadcast 00071 bool relay_udp_remote; // if true, relay incoming messages from the udp socket to the remote relays 00072 bool relay_tcp_remote; // if true, relay incoming messages from the incoming tcp sockets to the remote relay tcp sockets 00073 int udp_port; 00074 00075 public: 00076 struct Query 00077 { 00078 std::string typepattern; 00079 std::string titlepattern; 00080 std::string descpattern; 00081 std::string urlpattern; 00082 ServiceAdvertismentListener* listener; 00083 }; 00084 00085 private: 00086 std::map<int, Query> queries; 00087 00088 00089 public: 00090 00091 /** @name Options you can pass to the constructor */ 00092 //@{ 00093 static short LISTEN_BCAST; ///< Listen on local subnet UDP broadcast 00094 static short LISTEN_TCP; ///< Listen on TCP port 4229 00095 static short RELAY_TCP_TO_BCAST; ///< Relay from TCP ports to local broadcast 00096 static short RELAY_BCAST_TO_TCP; ///< Relay from local broadcast to remote TCP relay points. @see addRelay 00097 static short RELAY_TCP_TO_REMOTE; ///< Relay from incoming TCP ports to remote relay points (see addRelay) 00098 //@} 00099 00100 public: 00101 /** Constructor. 00102 @param options Mask of options: see above. Options may be combined with 00103 |. The defaults may be negated with ^ (e.g. ^ServiceDirectory::LISTEN_BCAST) 00104 */ 00105 ServiceDirectory(short options); 00106 00107 /** Constructor. Uses default options * LISTEN_BCAST|RELAY_TCP_TO_BCAST|RELAY_BCAST_TO_TCP */ 00108 ServiceDirectory(); 00109 00110 /** Destructor: all open sockets are shut down. */ 00111 virtual ~ServiceDirectory(); 00112 00113 /** Start a query on both this directory and remote directories for services which 00114 * match the given patterns. The listener is notified when a matching 00115 * service is found. 00116 * If any remote relays have been added, the query will also be sent to 00117 * each one (see addRelay()) 00118 * @return a unique identifier for this query 00119 */ 00120 virtual int query(const std::string& typepattern, 00121 const std::string& titlepattern, 00122 const std::string& descpattern, 00123 const std::string& urlpattern, 00124 ServiceAdvertismentListener* cb); 00125 00126 /** End query with identifier q */ 00127 virtual void endQuery(int q); 00128 00129 /** Add service to directory */ 00130 virtual void addService(Service* s); 00131 00132 /** Remove service from directory */ 00133 virtual void removeService(Service* s); 00134 00135 /** Check UDP and TCP sockets (via a call to select), and handle 00136 * incoming queries and advertisements from remote directories. 00137 * This method must be called periodically in order to maintain an 00138 * active directory. 00139 * @param timeout Timeout on select call, in seconds. Omit the parameter 00140 or use -1 to block until a socket has data. Use 0 to 00141 return immediately. 00142 */ 00143 virtual void handleIncoming(float timeout = -1); 00144 00145 00146 00147 /** Also relay queries via TCP to service directory running at the 00148 * given host and port. 00149 * Use with listenTCP() to span networks. 00150 */ 00151 virtual void addRelay(char* hostname, int port = 4229); 00152 00153 /** Don't relay queries to the specified directory */ 00154 virtual void removeRelay(char* hostname, int port = 4229); 00155 00156 /** Get UDP socket file descriptor */ 00157 virtual int getUDPfd() { return udp_fd; } 00158 00159 /** Get TCP socket file descriptor (listening) */ 00160 virtual int getTCPfd() { return tcp_fd; } 00161 00162 /** Get outgoing tcp remote relay file descriptors */ 00163 virtual std::deque<int> getRelayFds(); 00164 00165 /** Get incoming tcp file descriptors */ 00166 virtual std::deque<int> getIncomingTCPFds() ; 00167 00168 /** Listen on a TCP port for messages, which will be responded to in 00169 * handleIncoming(). 00170 * @param port Port to listen on. If -1, then any open TCP socket will 00171 * be closed. 00172 * 00173 * Call relayIncomingTCP() to cause handleIncoming() to also relay 00174 * messages to local broadcast. 00175 * Use with addRelay() to span networks with a symetrical set-up on 00176 * the other end. 00177 * This feature can also be used as a simple way to enable multiple 00178 * services to share a host's service directory. 00179 * 00180 * If you passed ServiceDirectory::LISTEN_TCP to the constructor, 00181 * then calling this is unnecessary. 00182 * 00183 * You can only listen on one TCP port. 00184 */ 00185 virtual void listenTCP(int port = 4229); 00186 00187 /** Listen on a UDP port for messages, which will be responded to in 00188 * handleIncoming(). 00189 * @param port Port to listen on. If -1, then any open TCP socket will 00190 * be closed. You want to use the default, 4230, unless the other 00191 * service directories on the socal net that you want to talk to are 00192 * using some other port for recieving udp broadcast messages. 00193 * 00194 * If you pass ServiceDirectory::LISTEN_BCAST to the constructor, 00195 * (the default argument) then calling this is unnecessary. 00196 * 00197 * You can only listen on one UDP port. 00198 */ 00199 virtual void listenUDP(int port = 4230); 00200 00201 /** Cause handleIncoming() to also relay incomming TCP messages broadcast to 00202 * local network (or stop relaying if argument is false). 00203 * 00204 * (Only useful if listenTCP() has been called or 00205 * ServiceDirectory::LISTEN_TCP was passed to the constructor. 00206 * Calling this is the same as passing 00207 * ServiceDirectory::RELAY_TCP_TO_BCAST|ServiceDirectory::LISTEN_TCP 00208 * to the constructor.) 00209 */ 00210 virtual void relayIncomingTCP(bool v = true) { 00211 relay_tcp_local = v; 00212 } 00213 }; 00214 00215 }; // namespace 00216 00217 #endif