Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Socket.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_Socket_h_
00003 #define INCLUDED_Socket_h_
00004 
00005 #ifdef PLATFORM_APERIOS
00006 #  include <ant.h>
00007 #  include <Types.h>
00008 #else
00009 #  include <sys/socket.h>
00010 #endif
00011 #include <stdarg.h>
00012 #include <stdlib.h>
00013 #include <string>
00014 
00015 //! holds socket enumerations and constants
00016 namespace SocketNS {
00017   
00018 #ifdef PLATFORM_APERIOS
00019   const int _SYS_SOCK_STREAM=1; //!< aperios doesn't provide SOCK_STREAM, so we will initialize them to these values
00020   const int _SYS_SOCK_DGRAM=2;  //!< aperios doesn't provide SOCK_DGRAM, so we will initialize them to these values
00021 #else
00022   //this is why you shouldn't use #define to declare constant values... grrr
00023   const int _SYS_SOCK_STREAM=SOCK_STREAM;
00024   const int _SYS_SOCK_DGRAM=SOCK_DGRAM;
00025 #  ifdef SOCK_STREAM
00026 #    undef SOCK_STREAM
00027 #  endif
00028 #  ifdef SOCK_DGRAM
00029 #    undef SOCK_DGRAM
00030 #  endif
00031 #endif
00032   //! Specifies transport type. TCP is usually a good idea
00033   enum TransportType_t {
00034     SOCK_STREAM=_SYS_SOCK_STREAM, //!< TCP: guaranteed delivery, higher overhead
00035     SOCK_DGRAM=_SYS_SOCK_DGRAM     //!< UDP: no guarantees, low overhead
00036   };
00037 
00038   //! Internal TCP/UDP Connection State
00039   enum ConnectionState {
00040     CONNECTION_CLOSED,
00041     CONNECTION_CONNECTING,
00042     CONNECTION_CONNECTED,
00043     CONNECTION_LISTENING,
00044     CONNECTION_CLOSING,
00045     CONNECTION_ERROR
00046   };
00047 
00048   //! Chooses between blocking and non-blocking Wireless Input, Output. Blocking wireless output from the main process will affect the performance of the Aibo, and should only be used for debugging purposes
00049   enum FlushType_t {
00050     FLUSH_NONBLOCKING=0, //!< Writes and Reads return immediately, and are processed by another process, so Main can continue to run. Non-blocking reads require specifying a callback function to handle data received
00051     FLUSH_BLOCKING       //!< Blocking writes are a good idea for debugging - a blocking write will be transmitted before execution continues to the next statement. Blocking reads should be avoided, since they'll cause a significant slow down in the main process
00052   };
00053 
00054 };
00055 
00056 using namespace SocketNS;
00057 
00058 #ifndef PLATFORM_APERIOS
00059   typedef unsigned char byte;
00060 #endif
00061 
00062 //! Tekkotsu wireless Socket class
00063 /*! 
00064  * For more information on using wireless, please read the following tutorials:
00065  * - <a href="../TekkotsuMon.html">TekkotsuMon</a>
00066  * - <a href="../Wireless.html">TCP/IP</a>
00067  *
00068  * The networking interface needs more documentation.  It also needs a
00069  * cleanup.  In the mean time, take a look at the TekkotsuMon objects
00070  * in <i>Tekkotsu</i><tt>/Behaviors/Mon</tt>.  They all listen for new
00071  * connections.  Unfortunately, at the momement there are no examples
00072  * of outgoing connections, but it should give you a pretty good idea
00073  * how to start moving.
00074  */
00075 
00076 class Socket {
00077   friend class Wireless;
00078 
00079 public:
00080   int sock; //!< unique non-negative integer representing socket. Serves as index into socket Objects array
00081 
00082 public:
00083   //! constructor
00084   explicit Socket(int sockn)
00085     : sock(sockn), trType(), flType(FLUSH_NONBLOCKING), verbosity(0), 
00086       endpoint(), state(CONNECTION_CLOSED), sendBufSize(), recvBufSize(),
00087       sendSize(0), sentSize(0), recvSize(0), writeSize(0), readSize(0),
00088       tx(false), rx(false), sendBuffer(), sendData(NULL), writeData(NULL), 
00089       recvBuffer(), recvData(NULL), readData(NULL), server_port(0), 
00090       rcvcbckfn(NULL), peer_addr(-1), peer_port(-1), textForward(false), textForwardBuf(NULL),
00091       forwardSock(NULL), daemon(false)
00092   {
00093 #ifndef PLATFORM_APERIOS
00094     endpoint=-1;
00095 #endif
00096   }
00097   virtual ~Socket(); //!< destructor
00098 
00099   //! use getWriteBuffer to get a memory address to write bytes to, for
00100   //! subsequent writing to a connection.
00101   /*!
00102    * The getWriteBuffer-write(int) combo eliminates one buffer copy. You
00103    * don't need to use getWriteBuffer with write(byte*, int)
00104    * @return pointer to the current position in the current write buffer for this socket or NULL on error
00105    * @param bytesreq maximum number of bytes the caller intends to set before the write method is called */
00106   byte* getWriteBuffer(int bytesreq);
00107 
00108   //! writes the specified number of bytes starting at the pointer returned.
00109   /*!
00110    * in a (prior) call to getWriteBufer
00111    * @param size number of bytes to be sent from the current write buffer
00112    */
00113   void write(int size);
00114 
00115   //! Blocking read. NOT IMPLEMENTED
00116   /*!
00117    * Tries to read upto receive buffer size worth of data from this socket.
00118    *
00119    * Blocking read is currently broken - it will be fixed in the next release
00120    * @return number of bytes read or -1 on error
00121    */
00122   int read();
00123 
00124   //! getReadBuffer is used with blocking read's NOT IMPLEMENTED
00125   /*!
00126    * The read(void) and getReadBuffer combo eliminates one buffer copy. You
00127    * don't need to use getReadBuffer with read(byte*, int)
00128    *
00129    * Blocking read is currently broken - it will be fixed in the next release
00130    * @return pointer to the buffer the previous call to blocking read wrote into or NULL if no data was read
00131    */
00132   byte* getReadBuffer();
00133   
00134   unsigned int getMaxSendSize() const { return sendBufSize; } //!< returns the maximum buffer size for a send
00135   unsigned int getMaxReceiveSize() const { return recvBufSize; } //!< returns the maximum buffer size for a receive
00136   unsigned int getAvailableSendSize() const { return sendBufSize-writeSize; } //!< returns the maximum *currently available* buffer size for a send
00137   unsigned int getAvailableReceiveSize() const { return recvBufSize; } //!< returns the maximum *currently available* buffer size for a receive
00138 
00139   //! initialize socket member variables. This is different from the constructor since sockets are reused
00140   void init(); 
00141 
00142   //! Chooses between blocking and non-blocking input, output.
00143   /*! This function
00144    * can only be called when a socket is disconnected, since it is a bad
00145    * idea to mix blocking and non-blocking input, output.
00146    * The default for a socket is non-blocking
00147    * @return 0 on success
00148    */
00149   int setFlushType(FlushType_t fType);
00150   //! returns flush mode
00151   FlushType_t getFlushType() const { return flType; }
00152   
00153   //! can choose between different transports; will reset the socket
00154   int setTransport(TransportType_t tr);
00155   //! returns the transport in use
00156   TransportType_t getTransport() const { return trType; }
00157 
00158   //!causes this socket to forward output to stdout if it is not connected, call setForward(NULL) to unset
00159   void setTextForward() { textForward=true; forwardSock=NULL; }
00160 
00161   //!causes this socket to forward output to @a sock if it is not connected, pass NULL to unset
00162   void setForward(Socket * forsock) { forwardSock=forsock; textForward=false; }
00163 
00164   //! Picks a level of verbosity for filtering pprintf commands.
00165   /*! The higher the
00166    * verbosity, the more the number of messages printed. This is useful
00167    * for filtering out non-important messages with very little processor
00168    * cost. Default is 0.
00169    * @param verbose the higher the value of verbose, the more the output
00170    */
00171   void setVerbosity(int verbose) { verbosity=verbose; }
00172 
00173   //! Standard write - writes specified amount of data from a buffer to a
00174   //! connection
00175   /*! You might want to consider the getWriteBuffer-write(int) combo if you
00176    * call this often
00177    * @param buf buffer to write from
00178    * @param size number of bytes to write
00179    * @return the number of bytes actually written or -1 on error
00180    */
00181   int write(const byte *buf, int size);
00182 
00183   //! Blocking read (NOT IMPLEMENTED)
00184   /*! You might want to consider the read(void) and getReadBuffer combo if you
00185    * call this often
00186    *
00187    * Blocking read is currently broken - it will be fixed in the next release
00188    * @param buf buffer to write from
00189    * @param size number of bytes to write
00190    * @return number of bytes actually read
00191    */
00192   int read(byte *buf, int size);
00193 
00194   //! It's standard stuff. man 3 printf on most systems should give you more
00195   //! information
00196   int printf(const char *fmt, ...) __attribute__((format(printf,2,3)));
00197 
00198   //! It's standard stuff. man 3 printf on most systems should give you more
00199   //! information
00200   int vprintf(const char *fmt, va_list al) __attribute__ ((format (printf, 2, 0)));
00201 
00202   //! Similar to printf, except it takes an extra first argument.
00203   /*! If vlevel is than or equal to the current #verbosity level,
00204    *  the string will be printed else it will be ignored.
00205    *  @param vlevel if (vlevel<=verbosity) print, else ignore
00206    *  @param fmt same as the standard printf's format string
00207    */
00208   int pprintf(int vlevel, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
00209   
00210   //! Initiate blocking or nonblocking write transfer depending on the type
00211   //! of socket.
00212   /*! All write commands on the socket will implicity call this. You
00213    * don't need to call it, unless you're implementing your own write
00214    */
00215   void flush();
00216   
00217   //! returns #daemon
00218   bool getDaemon() const { return daemon; }
00219   
00220   int getPeerAddress() const { return peer_addr; } //!< returns the address of the remote host in local host byte order
00221   std::string getPeerAddressAsString() const; //!< returns the address of the remote host as a human-readable string
00222   int getPeerPort() const { return peer_port; } //!< returns the port number that the remote host's socket is on
00223 
00224 protected:
00225   TransportType_t trType; //!< stores choice between transports (UDP or TCP (aka Datagram or Stream))
00226   FlushType_t flType; //!< blocking or non-blocking flushes... note that blocking flushes only block on the handoff to the system, not actual transmission (at least under aperios)
00227 
00228   int verbosity; //!< can be used to filter calls to pprintf
00229 
00230 #ifdef PLATFORM_APERIOS
00231   typedef antSharedBuffer buf_t; //!< the Aibo Networking Toolkit buffer data structure
00232   typedef antModuleRef endp_t; //!< the Aibo Networking Toolkit endpoint data structure
00233 #else
00234   typedef char* buf_t; //!< a general buffer
00235   typedef int endp_t; //!< a unix socket descriptor
00236 #endif
00237 
00238   endp_t endpoint; //!< holds the endpoint data structure for the host OS
00239   ConnectionState state; //!< an enum representing the current state of the socket
00240 
00241   int sendBufSize; //!< the size of the buffer for #sendData and #writeData
00242   int recvBufSize; //!< the size of the buffer for #readData and #recvData
00243   int sendSize; //!< the size of #sendData (total amount of data from last flush)
00244   int sentSize; //!< the sent portion of #sendData (amount of data which has been sent to system so far)
00245   int recvSize; //!< the size of #recvData (total amount of data returned by system)
00246   int writeSize; //!< the size of #writeData (amount of data so far ready to be flushed)
00247   int readSize; //!< the size of #readData (not used)
00248   bool tx; //!< a flag set when #sendData is in the process of being sent to the system
00249   bool rx; //!< not used, see #readData
00250 
00251   buf_t sendBuffer; //!< under aperios, a pointer to a shared region with the ip stack; under other OS, a pointer to a normal char * buffer
00252   byte *sendData; //!< a region within #sendBuffer, holding data in the process of being sent
00253   byte *writeData; //!< a region within #sendBuffer, holds data still being filled in by user code, not yet flushed
00254 
00255   buf_t recvBuffer; //!< under aperios, a pointer to a shared region with the ip stack; under other OS, a pointer to a normal char * buffer
00256   byte *recvData; //!< a region within #recvBuffer, holding data either just filled in by ip stack (during call to #rcvcbckfn), or in the process of being filled in (any other time)
00257   byte *readData; //!< not used (available for double buffering, but not implemented)
00258   
00259   int server_port; //!< if the socket is a server socket, this is the port it is listening on
00260   int (*rcvcbckfn) (char*, int); //!< pointer to callback function, called after #recvData has been filled in
00261   
00262   int peer_addr; //!< inet address of peer (if connected) or last message sender (if udp and bound); -1 otherwise (in host byte-order, not network byte-order!)
00263   int peer_port; //!< port of peer (if connected) or last message sender (if udp and bound); -1 otherwise
00264 
00265   bool textForward; //!< if true, when data is sent to the socket and the socket is not current connected, the data will be sent to stdout (overridden by #forwardSock)
00266   char* textForwardBuf; //!< temporary buffer allocated in getWriteBuffer() and freed in write(), if the output is destined for stdout (#textForward)
00267   Socket * forwardSock; //!< if non-NULL, output will be sent to this socket if the current socket is not otherwise connected (overrides #textForward)
00268 
00269   bool daemon; //!< if true, the socket will automatically be reopened after any closure (manual or otherwise)
00270  
00271 protected:
00272   Socket(const Socket&); //!< copy constructor, don't call
00273   Socket& operator= (const Socket&); //!< assignment operator, don't call
00274 };
00275 
00276 extern Socket* sout;  //!< the standard tekkotsu in/out console (default port 10001)
00277 extern Socket* serr;  //!< the standard tekkotsu error output (default port 10002)
00278 
00279 /*! @file
00280  * @brief Defines Tekkotsu wireless Socket class, also sout and serr
00281  * @author alokl (Creator)
00282  * 
00283  * $Author: ejt $
00284  * $Name: tekkotsu-3_0 $
00285  * $Revision: 1.27 $
00286  * $State: Exp $
00287  * $Date: 2006/10/03 22:32:49 $
00288  */
00289 
00290 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:46 2006 by Doxygen 1.4.7