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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:51 2016 by Doxygen 1.6.3