Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
Socket.hGo 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 |