spocket.h

Go to the documentation of this file.
00001 #ifndef SPOCKET_CLASS
00002 #define SPOCKET_CLASS
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : spocket                                                           *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *  Purpose:                                                                   *
00010 *                                                                             *
00011 *    Abstraction for a BSD socket that is platform independent, as least as   *
00012 *  far as working on Win32 or Unix operating systems.  This class is named    *
00013 *  after the venerable Vulcan Spock to avoid name conflicts with the OS's     *
00014 *  socket() function.                                                         *
00015 *                                                                             *
00016 *******************************************************************************
00017 * Copyright (c) 1989-$now By Author.  This program is free software; you can  *
00018 * redistribute it and/or modify it under the terms of the GNU General Public  *
00019 * License as published by the Free Software Foundation; either version 2 of   *
00020 * the License or (at your option) any later version.  This is online at:      *
00021 *     http://www.fsf.org/copyleft/gpl.html                                    *
00022 * Please send any updates to: fred@gruntose.com                               *
00023 \*****************************************************************************/
00024 
00025 #include "definitions_sockets.h"
00026 
00027 #include <basis/object_base.h>
00028 
00029 // forward.
00030 class internet_address;
00031 class raw_socket;
00032 class tcpip_stack;
00033 class time_stamp;
00034 
00035 class SOCKETS_CLASS_STYLE spocket : public virtual object_base
00036 {
00037 public:
00038   enum sock_types {
00039     CONNECTED,         // connected socket over TCP.
00040     BROADCAST,         // broadcasting socket over UDP.
00041     UNICAST,           // single-address targeted socket over UDP.
00042     BOGUS_SOCK         // special type that goes nowhere and provides no data.
00043   };
00044 
00045   spocket(const internet_address &where, sock_types type = CONNECTED);
00046     // constructs the spocket object.  "where" provides the network location
00047     // for either this side (for a server) or the other side (for a client).
00048     // the decision about this socket's orientation (client or server) will not
00049     // be made until either connect() or accept() are invoked.  note however
00050     // that BROADCAST sockets are only appropriate for use as a client; they
00051     // can receive and send broadcasts that way without needing a server role.
00052 
00053   ~spocket();
00054     // drops any connection that was made and destroys the spocket object.
00055 
00056   IMPLEMENT_CLASS_NAME("spocket");
00057 
00058   bool healthy();
00059     // returns true if the spocket seems to be okay.
00060 
00061   const internet_address &where() const;
00062     // returns the location where this socket exists.
00063 
00064   const internet_address &remote() const;
00065     // returns the location that we have accepted from.
00066 
00067   enum outcomes {
00068     OKAY = common::OKAY,
00069     TIMED_OUT = common::TIMED_OUT,
00070     ACCESS_DENIED = common::ACCESS_DENIED,
00071     BAD_INPUT = common::BAD_INPUT,
00072     NONE_READY = common::NONE_READY,
00073     PARTIAL = common::PARTIAL,
00074 
00075     NO_CONNECTION = communication_commons::NO_CONNECTION,
00076     NO_ANSWER = communication_commons::NO_ANSWER,
00077 
00078     DEFINE_OUTCOME(NOT_SERVER, -39, "Accept was tried on a spocket that is "
00079         "not a root server")
00080   };
00081   
00082   static const char *outcome_name(const outcome &to_name);
00083     // returns the text for "to_name" if it's a member of spocket outcomes.
00084 
00085   // informative functions...
00086 
00087   istring text_form();
00088     // returns a readable version of the contents of the spocket.
00089 
00090   inline bool was_connected() const { return _was_connected; }
00091     // a simple check of whether a connection has been made on this object.
00092     // if this is not true, then the object is not usable yet.  this state
00093     // will also get set to false when the spocket gets disconnected.
00094 
00095   bool connected();
00096     // returns true if the spocket is "currently" connected.  this causes an
00097     // interrogation of the operating system and may take a short while.
00098 
00099   // these report what type of spocket this is.
00100   bool is_client() const { return _client; }
00101   bool is_server() const { return !_client; }
00102   bool is_root_server() const { return is_server() && !!_server_socket; }
00103 
00104   u_int OS_socket() { return _socket; }
00105     // returns the low-level operating system form of our normal action socket.
00106     // this is zero for a root server.  note: this will still record what the
00107     // socket was after it is closed out, just for record keeping; do not
00108     // control the returned socket outside of this class.
00109   u_int OS_root_socket() { return _server_socket; }
00110     // returns the OS form of our server socket, but only if this is a root
00111     // server type of socket.
00112 
00113   void bind_client(const internet_address &source);
00115 
00119   // major operations for connected mode sockets...
00120 
00121   outcome connect(int communication_wait = 20 * SECOND_ms);
00122     // acts as a client and connects to a destination.  the timeout is
00123     // specified in milliseconds by "communication_wait".  this can be as low
00124     // as zero if you don't want to wait.  TIMED_OUT is returned if the
00125     // connection hasn't finished within the connection_wait.  OKAY is returned
00126     // if the connection succeeded.  other outcomes denote failures.
00127 
00128   outcome accept(spocket * &sock, bool wait);
00129     // makes this spocket act as a root server and accepts a connection from a
00130     // client if possible.  a root server is a spocket object that manages a
00131     // server spocket but which does not allow any normal sending or receiving.
00132     // only root servers can have accept called on them.  the "sock" will be
00133     // a normal server spocket which can be used to send and receive if it
00134     // got connected.  for "sock" to be valid, it must not be returned as NIL
00135     // and the returned outcome must be OKAY.  if no new connections are
00136     // available, then NO_CONNECTION is returned.  if the "wait" flag is true,
00137     // then the accept on the root server will block until a connection is
00138     // accepted and the returned spocket will be made non-blocking.  if "wait"
00139     // is false, then no blocking will occur at all.  note that multiple
00140     // threads can invoke this without tripping over the protective locking;
00141     // once the root socket is initialized, accept will not lock the spocket.
00142 
00143   outcome disconnect();
00144     // closes the connection.  the state is returned to the post-construction
00145     // state, i.e. it will appear that this object had never connected yet.
00146 
00147   // these report which side of the connection this is functioning as.
00148   bool client() const { return _client; }
00149   bool server() const { return !_client; }
00150 
00151   // send and receive functions...
00152   //
00153   //   if the outcome from one of these is NO_CONNECTION, then somehow the
00154   // connection has dropped or never succeeded.
00155 
00156   outcome send(const byte *buffer, int size, int &len_sent);
00157     // sends "size" bytes from the "buffer".  the number actually sent is
00158     // stored in "len_sent".  this can only be used for CONNECTED type sockets.
00159 
00160   outcome send(const byte_array &to_send, int &len_sent);
00161     // this version takes a byte_array.
00162 
00163   outcome send_to(const internet_address &where_to, const byte *buffer,
00164           int size, int &len_sent);
00165     // this version is used for sending when the socket type is BROADCAST
00166     // or UNICAST.
00167 
00168   outcome send_to(const internet_address &where_to, const byte_array &to_send,
00169           int &len_sent);
00170     // clone of above, using byte_array.
00171 
00172   outcome receive(byte *buffer, int &size);
00173     // attempts to retrieve data from the spocket and place it in the "buffer".
00174     // the "size" specifies how much space is available.  if successful, the
00175     // buffer will be filled with data and "size" will report how much there
00176     // actually is.
00177 
00178   outcome receive(byte_array &buffer, int &size);
00179     // this version uses a byte_array for the "buffer".  the "size" expected
00180     // must still be set and "size" will still report the bytes read.
00181 //hmmm: could remove the size parameter for byte array type.
00182 
00183   // these methods are used for BROADCAST and other non-connected types of
00184   // spockets.  they report the data as the above receive methods do, but they
00185   // also report the sender.
00186   outcome receive_from(byte *buffer, int &size,
00187           internet_address &where_from);
00188   outcome receive_from(byte_array &buffer, int &size,
00189           internet_address &where_from);
00190 
00191   outcome await_readable(int timeout);
00192     // pauses this caller until data arrives.  this is a blocking call that
00193     // could potentially not return until the "timeout" elapses (measured in
00194     // milliseconds).  if "timeout" is zero, then this really doesn't do
00195     // anything.  if data is available, then OKAY is returned.
00196 
00197   outcome await_writable(int timeout);
00198     // pauses this caller until the socket can be written to again.  could
00199     // potentially not return until the "timeout" elapses (measured in
00200     // milliseconds).  if "timeout" is zero, then this really doesn't do
00201     // anything.  if the socket is able to send again, then OKAY is returned.
00202     // otherwise NONE_READY is returned.
00203 
00204   tcpip_stack &stack() const;
00205     // provides access to the spocket's tcpip stack to derivative objects.
00206 
00207   bool is_bogus() const { return _type == BOGUS_SOCK; }
00209 
00215 private:
00216   sock_types _type;  // records what kind of socket we'll create.
00217   u_int _socket;  // our socket that we communicate on.
00218   u_int _server_socket;  // our serving socket, if we're a root server.
00219   bool _was_connected;  // did we ever successfully connect?
00220   bool _client;  // true if we are acting as a client.
00221   internet_address *_where;  // our addressing info.
00222   internet_address *_remote;  // our addressing info.
00223   raw_socket *_socks;  // provides low-level socket functionality.
00224   tcpip_stack *_stack;  // provides access to socket facilities.
00225   mutex *_select_lock;  // protects concurrent access to socket.
00226   time_stamp *_last_resolve;
00227     // tracks when we last tried a resolve on our address.  if they try to
00228     // reconnect and we haven't done this in a while, we'll re-resolve the
00229     // socket.
00230   bool _client_bind;  
00231   internet_address *_cli_bind;  
00232 
00233   // not allowed.
00234   spocket(const spocket &);
00235   spocket &operator =(const spocket &);
00236 };
00237 
00238 #endif
00239 

Generated on Fri Nov 21 04:29:17 2008 for HOOPLE Libraries by  doxygen 1.5.1