Panda3D

socket_tcp.h

00001 #ifndef __SOCKET_TCP_H__
00002 #define __SOCKET_TCP_H__ 
00003 
00004 #include "pandabase.h"
00005 #include "socket_ip.h"
00006 
00007 /////////////////////////////////////////////////////////////////////
00008 // Class : Socket_TCP
00009 //
00010 // Description : Base functionality for a TCP connected socket
00011 //               This class is pretty useless by itself but it does hide some of the
00012 //               platform differences from machine to machine
00013 //
00014 /////////////////////////////////////////////////////////////////////
00015 class EXPCL_PANDA_NATIVENET Socket_TCP : public Socket_IP
00016 {
00017 public:    
00018 PUBLISHED:
00019     inline Socket_TCP(SOCKET);
00020     inline Socket_TCP()    {   };    
00021     inline int  SetNoDelay(bool flag = true);
00022     inline int  SetLinger(int interval_seconds = 0);
00023     inline int  DontLinger();    
00024     inline int  SetSendBufferSize(int insize);
00025     //inline bool ActiveOpen(const Socket_Address & theaddress);
00026     inline bool ActiveOpen(const Socket_Address & theaddress, bool setdelay);
00027     inline bool ActiveOpenNonBlocking(const Socket_Address & theaddress);
00028     inline bool ErrorIs_WouldBlocking(int err);
00029     inline bool ShutdownSend();
00030     inline int  SendData(const std::string &str);
00031 //    inline int RecvData( std::string &str, int max_len);
00032 
00033     std::string RecvData(int max_len);
00034 public:
00035     inline int  SendData(const char * data, int size);
00036     inline int  RecvData(char * data, int size);
00037   
00038 public:
00039   static TypeHandle get_class_type() {
00040     return _type_handle;
00041   }
00042   static void init_type() {
00043     Socket_IP::init_type();
00044     register_type(_type_handle, "Socket_TCP",
00045                   Socket_IP::get_class_type());
00046   }
00047   virtual TypeHandle get_type() const {
00048     return get_class_type();
00049   }
00050   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00051 
00052 private:
00053   static TypeHandle _type_handle;
00054 };
00055 
00056 //////////////////////////////////////////////////////////////
00057 // Function name : Socket_TCP::Socket_TCP
00058 // Description   :
00059 //////////////////////////////////////////////////////////////
00060 inline Socket_TCP::Socket_TCP(SOCKET sck) : ::Socket_IP(sck)
00061 {
00062 }
00063 
00064 ////////////////////////////////////////////////////////////////////
00065 // Function name : SetNoDelay
00066 // Description   : Disable Nagle algorithm. Don't delay send to coalesce packets
00067 ////////////////////////////////////////////////////////////////////
00068 inline int Socket_TCP::SetNoDelay(bool flag)
00069 {
00070     int nodel = flag;
00071     int ret1;
00072     ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel));
00073     
00074     if (ret1 != 0)
00075         return BASIC_ERROR;
00076     
00077     return ALL_OK;
00078 }
00079 
00080 ////////////////////////////////////////////////////////////////////
00081 // Function name : SetLinger
00082 // Description   : will control the behavior of SO_LINGER for a TCP socket
00083 ////////////////////////////////////////////////////////////////////
00084 int Socket_TCP::SetLinger(int interval_seconds)
00085 {
00086     linger ll;
00087     ll.l_linger = interval_seconds;
00088     ll.l_onoff = 1;
00089     int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
00090     if (ret1 != 0)
00091         return BASIC_ERROR;
00092     return ALL_OK;
00093 }
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 // Function name : Socket_TCP::DontLinger
00097 // Description   : Turn off the linger flag. The socket will quickly release
00098 //        buffered items and free up OS resources. You may lose
00099 //        a stream if you use this flag and do not negotiate the close
00100 //        at the application layer.
00101 ////////////////////////////////////////////////////////////////////
00102 int Socket_TCP::DontLinger()
00103 {
00104     linger ll;
00105     ll.l_linger = 0;
00106     ll.l_onoff = 0;
00107     int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
00108     if (ret1 != 0)
00109         return BASIC_ERROR;
00110     return ALL_OK;
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 // Function name : SetSendBufferSize
00115 // Description   : Just like it sounds. Sets a buffered socket recv buffer size.
00116 //      This function does not refuse ranges outside hard-coded OS
00117 //      limits
00118 ////////////////////////////////////////////////////////////////////
00119 int Socket_TCP::SetSendBufferSize(int insize)
00120 {
00121     if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int)))
00122         return BASIC_ERROR;
00123     return ALL_OK;
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 // Function name : ActiveOpen
00128 // Description   : This function will try and set the socket up for active open to a specified
00129 //       address and port provided by the input parameter
00130 ////////////////////////////////////////////////////////////////////
00131 bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress, bool setdelay)
00132 {
00133     _socket = DO_NEWTCP();
00134     if (_socket == BAD_SOCKET)
00135         return false;
00136 
00137     if(setdelay)
00138         SetNoDelay();
00139     
00140     if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
00141         return ErrorClose();
00142     
00143     return true;
00144 }
00145 
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 // Function name : ActiveOpenNonBlocking
00149 // Description   : This function will try and set the socket up for active open to a specified
00150 //       address and port provided by the input parameter (non-blocking version)
00151 ////////////////////////////////////////////////////////////////////
00152 bool Socket_TCP::ActiveOpenNonBlocking(const Socket_Address & theaddress)
00153 {
00154     _socket = DO_NEWTCP();
00155     if (_socket == BAD_SOCKET)
00156         return false;
00157     
00158     SetNonBlocking();
00159     SetReuseAddress();
00160     
00161     if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) {
00162         if (GETERROR() != LOCAL_CONNECT_BLOCKING)
00163         {
00164             printf(" None Blockign Connect Error %d",GETERROR());
00165             return ErrorClose();
00166         }
00167     }
00168         
00169     return true;
00170 }
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 // Function name : Socket_TCP::SendData
00174 // Description   : Ok Lets Send the Data
00175 //
00176 // Return type  : int
00177 //      - if error
00178 //      0 if socket closed for write or lengh is 0
00179 //      + bytes writen ( May be smaller than requested)
00180 ////////////////////////////////////////////////////////////////////
00181 inline int Socket_TCP::SendData(const char * data, int size)
00182 {
00183     return DO_SOCKET_WRITE(_socket, data, size);
00184 }
00185 
00186 ////////////////////////////////////////////////////////////////////
00187 // Function name : Socket_TCP::RecvData
00188 // Description   : Read the data from the connection
00189 //
00190 // Return type  : int
00191 //      - if error
00192 //      0 if socket closed for read or length is 0
00193 //      + bytes read ( May be smaller than requested)
00194 ////////////////////////////////////////////////////////////////////
00195 inline int Socket_TCP::RecvData(char * data, int len)
00196 {
00197     int ecode = DO_SOCKET_READ(_socket, data, len);
00198     return ecode;
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 // Function name : Socket_TCP::RecvData
00203 // Description   : Read the data from the connection
00204 //
00205 // Return type  : int
00206 //      - if error
00207 //      0 if socket closed for read or length is 0
00208 //      + bytes read ( May be smaller than requested)
00209 ////////////////////////////////////////////////////////////////////
00210 inline std::string  Socket_TCP::RecvData(int max_len)
00211 {
00212     std::string str;
00213     char    *buffer = (char *) malloc(max_len+1);
00214     int ecode  = RecvData(buffer,max_len);
00215     if(ecode > 0)
00216         str.assign(buffer,ecode);
00217 
00218     free(buffer);
00219     return str;
00220 };
00221 
00222 
00223 inline bool Socket_TCP::ErrorIs_WouldBlocking(int err)
00224 {
00225     return (GETERROR() == LOCAL_BLOCKING_ERROR);
00226 }
00227 
00228 inline bool Socket_TCP::ShutdownSend()
00229 {
00230     return do_shutdown_send(_socket);
00231 };
00232 
00233 /*
00234 inline bool Socket_TCP::DoNotLinger()
00235 {
00236     int bOption = 1;
00237     if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0)
00238         return false;
00239     return true;
00240 }
00241 */
00242 
00243 inline int Socket_TCP::SendData(const std::string &str)
00244 {
00245     return SendData(str.data(), str.size());
00246 };
00247 
00248 #endif //__SOCKET_TCP_H__
 All Classes Functions Variables Enumerations