netlib.h

Go to the documentation of this file.
00001 /*
00002  * netlib.h
00003  *
00004  * Copyright (C) 2007,2009,2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Networking library.  This is a layer on top of BSD sockets that handles
00032  * some threading etc.  Somewhat tailored to my specific applications.
00033  */
00034 
00035 #ifndef WAVEPACKET_NETLIB_H__
00036 #define WAVEPACKET_NETLIB_H__
00037 
00038 
00039 // includes --------------------------------------------------------------------
00040 #include "message-buffer.h"
00041 #include "wavesock.h"
00042 
00043 
00044 namespace netlib {
00045 
00046 
00047 // networking typedefs ---------------------------------------------------------
00048 
00049 ////////////////////////////////////////////////////////////////////////////////
00050 ///
00051 /// \ingroup networking
00052 /// \defgroup netlib Networking API
00053 ///
00054 ///     This is a very basic networking API layer.  You can create connections
00055 ///     (using the various constructors) and get back a connection ID.  Then
00056 ///     you can read/write to the connection based on the ID.
00057 ///
00058 ///     You can write to the connection any time using the connection ID.
00059 ///
00060 ///     <b>The getNextMessage() API is the core message pump.</b>
00061 ///     The application should repeatedly call this so that messages get sent
00062 ///     in and out.
00063 ///
00064 ///     \b WARNING: this library is NOT threadsafe!  You should handle any
00065 ///     synchronization issues at a higher layer.
00066 ///
00067 ////////////////////////////////////////////////////////////////////////////////
00068 /*@{*/
00069 
00070 /// connection ID type.  Will never be null for a valid connection.
00071 typedef dword_t conn_id_t;
00072 
00073 
00074 /// the type of connection
00075 enum eConnectionType {
00076         eType_TCP               = 0x0001,       ///< standard tcp/ip connection
00077         eType_SecureTCP         = 0x0002,       ///< ssl connection
00078 
00079         eType_UDPLocal          = 0x0010,       ///< can send/receive UDP datagrams
00080         eType_UDPRemote         = 0x0020,       ///< our record of remote UDP socket
00081         eType_UDPBroadcast      = 0x0040,       ///< can broadcast UDP datagrams
00082 
00083         eType_TCPListener       = 0x0100,       ///< local tcp listening socket
00084 
00085         // must be last!
00086         eType_Invalid           = 0
00087 };
00088 
00089 
00090 
00091 struct connection_info_t {
00092         // constructor, manipulator
00093         connection_info_t(void) throw() { this->clear(); }
00094         void clear(void) throw() {
00095                         type = eType_Invalid;
00096                         address.clear();
00097                         port = 0;
00098                 }
00099         bool is_valid(void) const throw() {
00100                         return (eType_Invalid != type);
00101                 }
00102         void dump(IN const char * title) const throw();
00103 
00104         // data fields
00105         eConnectionType         type;
00106         address_t               address;
00107         int                     port;
00108 };
00109 
00110 
00111 
00112 /// An envelope describes from where and how a remote message arrived
00113 struct envelope_t {
00114         // constructor, manipulators
00115         envelope_t(void) throw() { this->clear(); }
00116         void clear(void) throw() {
00117                         fromConnId = 0;
00118                         type = eType_Invalid;
00119                         address.clear();
00120                 }
00121         bool is_empty(void) const throw() {
00122                         return (eType_Invalid == type);
00123                 }
00124         bool isValid(void) const throw() {
00125                         if (eType_Invalid == type)
00126                                 return false;
00127                         if (fromConnId)
00128                                 return true;    // assume so...
00129                         return address.isValid();
00130                 }
00131 
00132         // data fields
00133         conn_id_t               fromConnId;     /// source connection ID
00134         eConnectionType         type;
00135         address_t               address;
00136 };
00137 
00138 
00139 
00140 
00141 ////////////////////////////////////////////////////////////////////////////////
00142 //
00143 //      public API
00144 //
00145 ////////////////////////////////////////////////////////////////////////////////
00146 /// \ingroup netlib
00147 /*@{*/
00148 
00149 
00150 /// return the hostname (or IP in string form!)
00151 std::string getServerFromIP(IN const ip_addr_t& ip);
00152 
00153 
00154 /// create a listener (if clients connect, you'll see their messages show up)
00155 conn_id_t createTcpListener(IN const address_t& address,
00156                                 IN int maxBacklog);
00157 
00158 /// create a connection to a remote peer (connection ID is returned)
00159 conn_id_t createTcpConnection(IN const address_t& address);
00160 
00161 
00162 /// create a local UDP connection for sending/receiving datagrams.
00163 /// This connection will receive datagrams sent to this local port from any
00164 ///     remote location (including broadcast packets).
00165 /// You have to specify the full local address.  This is important for
00166 ///     machines with multiple interfaces, and even for a machine with a
00167 ///     single interface, you need to specify the physical interface vs.
00168 ///     a local host loopback (127.0.0.1).
00169 /// To send UDP datagrams from this connection, create a remote UDP
00170 ///     connection using createUdpRemote() and use this connection as the
00171 ///     localUdp connection.
00172 /// To broadcast UDP datagrams, you won't use this connection at all.  Instead,
00173 ///     create a broadcast UDP datagram connection using createUdpBroadcast().
00174 conn_id_t createUdpLocal(IN const address_t& localUdp);
00175 
00176 /// create a logical connection to represent a remote UDP sender/receiver
00177 ///  - caller must specify the local UDP connection that will communicate
00178 /// this is used for sending to remote UDP listeners
00179 conn_id_t createUdpRemote(IN conn_id_t localUdp,
00180                                 IN const address_t& address);
00181 
00182 /// create a local UDP sending point for datagram broadcasts to a specific port.
00183 /// Caller must specify the broadcast address, such as 192.168.0.255 
00184 conn_id_t createUdpBroadcast(IN const address_t& broadcastAddress);
00185 
00186 
00187 /// asynchronously send data to a particular connection
00188 /// -  conn_id specifies the (remote) receiver
00189 /// -  queued messages are actually sent via getNextMessage() calls
00190 bool enqueueMessage(IN conn_id_t connId,
00191                                 IN smart_ptr<MessageBuffer>& message);
00192 
00193 
00194 /// get next message from all open connections (empty if no messages waiting)
00195 ///  - this is the main message pump so applications should keep calling it
00196 bool getNextMessage(IN long wait_microseconds,
00197                                 OUT netlib::envelope_t& envelope,
00198                                 OUT smart_ptr<MessageBuffer>& buffer);
00199 
00200 
00201 /// is this a valid connection?
00202 bool isValidConnection(IN conn_id_t conn_id);
00203 
00204 
00205 /// given a connection, retrieve information about it
00206 bool getConnectionInfo(IN conn_id_t conn_id,
00207                                 OUT connection_info_t& info);
00208 
00209 /// terminate a particular connection
00210 void closeConnection(IN conn_id_t conn_id);
00211 
00212 /// for debugging
00213 void dumpMessage(IO std::ostream& stream,
00214                                 IN const char * title,
00215                                 IN const envelope_t& envelope,
00216                                 IN const MessageBuffer * buffer);
00217 
00218 /// info only
00219 void dumpStats(void);
00220 
00221 
00222 };      // netlib namespace
00223 
00224 
00225 
00226 #endif  // WAVEPACKET_NETLIB_H__
00227