NetServerTCPProtocol.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <net/NetServerTCPProtocol.h>
00022 #include <net/NetServerTCPRead.h>
00023 #include <net/NetMessagePool.h>
00024 #include <common/Logger.h>
00025 
00026 NetServerTCPProtocol::NetServerTCPProtocol()
00027 {
00028 }
00029 
00030 NetServerTCPProtocol::~NetServerTCPProtocol()
00031 {
00032 }
00033 
00034 NetServerTCPScorchedProtocol::NetServerTCPScorchedProtocol()
00035 {
00036 }
00037 
00038 NetServerTCPScorchedProtocol::~NetServerTCPScorchedProtocol()
00039 {
00040 }
00041 
00042 bool NetServerTCPScorchedProtocol::sendBuffer(NetBuffer &buffer, TCPsocket socket, unsigned int id)
00043 {
00044         Uint32 len = buffer.getBufferUsed();
00045         Uint32 netlen=0;
00046         SDLNet_Write32(len, &netlen);
00047 
00048         // send the length of the string
00049         int result = SDLNet_TCP_Send(socket, &netlen, sizeof(netlen));
00050         if(result<(int) sizeof(netlen))
00051         {
00052                 Logger::log(S3D::formatStringBuffer("Failed to send buffer length. Sent %i of %i.",
00053                         result, sizeof(netlen)));
00054                 return false;
00055         }
00056         
00057         // send the buffer
00058         result = SDLNet_TCP_Send(socket,buffer.getBuffer(),len);
00059         if(result<int(len))
00060         {
00061                 Logger::log(S3D::formatStringBuffer("Failed to send buffer. Sent %i of %i.",
00062                         result, int(len)));
00063                 return false;
00064         }
00065         NetInterface::getBytesOut() += len;
00066         
00067         // return the length sent
00068         return true;
00069 }
00070 
00071 static bool realSDLNet_TCP_Recv(TCPsocket socket, char *dest, int len)
00072 {
00073         int result = 0;
00074         while (len > 0)
00075         {
00076                 int recv = SDLNet_TCP_Recv(socket, &dest[result], len);
00077                 if (recv <= 0) 
00078                 {
00079                         return false;
00080                 }
00081 
00082                 result += recv;
00083                 len -= recv;
00084 
00085                 if (len > 0)
00086                 {
00087                         //Logger::log( "Partial read, %i/%i %s", recv, len + recv, 
00088                                 //SDLNet_GetError());
00089                         SDL_Delay(10);
00090                 }
00091         }       
00092 
00093         return true;
00094 }
00095 
00096 NetMessage *NetServerTCPScorchedProtocol::readBuffer(TCPsocket socket, unsigned int id)
00097 {
00098         // receive the length of the string message
00099         char lenbuf[4];
00100         if (!realSDLNet_TCP_Recv(socket, lenbuf, 4))
00101         {
00102                 Logger::log( "Socket closed.");
00103                 return 0;
00104         }
00105 
00106         // swap byte order to our local order
00107         Uint32 len = SDLNet_Read32(lenbuf);
00108         
00109         // check if anything is strange, like a zero length buffer
00110         if(len == 0)
00111         {
00112                 Logger::log( "Zero length buffer recieved.");
00113                 return 0;
00114         }
00115 
00116         // Cannot recieve a message large than .5 MB
00117         if (len > 5000000)
00118         {
00119                 Logger::log(S3D::formatStringBuffer("Buffer was too large to recieve.  Size %i.",
00120                         len));
00121                 return 0;
00122         }
00123 
00124         // allocate the buffer memory
00125         NetMessage *buffer = NetMessagePool::instance()->
00126                 getFromPool(NetMessage::BufferMessage, 
00127                                 id,
00128                                 NetServerTCPRead::getIpAddressFromSocket(socket));
00129         buffer->getBuffer().allocate(len);
00130         buffer->getBuffer().setBufferUsed(len);
00131 
00132         // get the string buffer over the socket
00133         if (!realSDLNet_TCP_Recv(socket, 
00134                 buffer->getBuffer().getBuffer(),
00135                 len))
00136         {
00137                 Logger::log( "Read failed for buffer");
00138                 NetMessagePool::instance()->addToPool(buffer);
00139                 return 0;
00140         }
00141         NetInterface::getBytesIn() += len;
00142 
00143         // return the new buffer
00144         return buffer;
00145 }
00146 
00147 
00148 NetServerHTTPProtocolSend::NetServerHTTPProtocolSend()
00149 {
00150 }
00151 
00152 NetServerHTTPProtocolSend::~NetServerHTTPProtocolSend()
00153 {
00154 }
00155 
00156 bool NetServerHTTPProtocolSend::sendBuffer(NetBuffer &buffer, TCPsocket socket, unsigned int id)
00157 {
00158         Uint32 len = buffer.getBufferUsed();
00159         
00160         // send the buffer
00161         int result = SDLNet_TCP_Send(socket,buffer.getBuffer(),len);
00162         if(result<int(len))
00163         {
00164                 Logger::log(S3D::formatStringBuffer("Failed to send HTTP buffer. Sent %i of %i.",
00165                         result, int(len)));
00166                 return false;
00167         }
00168         NetInterface::getBytesOut() += len;
00169         
00170         // return the length sent
00171         return true;
00172 }
00173 
00174 NetMessage *NetServerHTTPProtocolSend::readBuffer(TCPsocket socket, unsigned int id)
00175 {
00176         // allocate the buffer memory
00177         NetMessage *netBuffer = NetMessagePool::instance()->
00178                 getFromPool(NetMessage::BufferMessage,
00179                                 id,
00180                                 NetServerTCPRead::getIpAddressFromSocket(socket));
00181         netBuffer->getBuffer().reset();
00182 
00183         // get the string buffer over the socket
00184         Uint32 len = 0;
00185         char buffer[1];
00186         for (;;)
00187         {
00188                 int recv = SDLNet_TCP_Recv(socket, buffer, 1);
00189                 if (recv <= 0) 
00190                 {
00191                         // For HTTP the socket being closed signifies the end
00192                         // of the transmission and is probably not an error!
00193                         if (len == 0)
00194                         {
00195                                 // If the len is zero then we have been disconnected
00196                                 NetMessagePool::instance()->addToPool(netBuffer);
00197                                 return 0;
00198                         }
00199                         else break;
00200                 }
00201 
00202                 netBuffer->getBuffer().addDataToBuffer(buffer, 1);
00203                 len += 1;
00204         }
00205         NetInterface::getBytesIn() += len;
00206 
00207         // return the new buffer
00208         return netBuffer;
00209 }
00210 
00211 NetServerHTTPProtocolRecv::NetServerHTTPProtocolRecv()
00212 {
00213 }
00214 
00215 NetServerHTTPProtocolRecv::~NetServerHTTPProtocolRecv()
00216 {
00217 }
00218 
00219 bool NetServerHTTPProtocolRecv::sendBuffer(NetBuffer &buffer, TCPsocket socket, unsigned int id)
00220 {
00221         Uint32 len = buffer.getBufferUsed();
00222         
00223         // send the buffer
00224         int result = SDLNet_TCP_Send(socket,buffer.getBuffer(),len);
00225         if(result<int(len))
00226         {
00227                 Logger::log(S3D::formatStringBuffer("Failed to send HTTP buffer. Sent %i of %i.",
00228                         result, int(len)));
00229                 return false;
00230         }
00231         NetInterface::getBytesOut() += len;
00232         
00233         // return the length sent
00234         return true;
00235 }
00236 
00237 NetMessage *NetServerHTTPProtocolRecv::readBuffer(TCPsocket socket, unsigned int id)
00238 {
00239         // allocate the buffer memory
00240         NetMessage *netBuffer = NetMessagePool::instance()->
00241                 getFromPool(NetMessage::BufferMessage,
00242                                 id,
00243                                 NetServerTCPRead::getIpAddressFromSocket(socket));
00244         netBuffer->getBuffer().reset();
00245 
00246         // get the string buffer over the socket
00247         unsigned int len = 0;
00248         unsigned int dataLen = 0;
00249         char buffer[1];
00250         for (;;)
00251         {
00252                 int recv = SDLNet_TCP_Recv(socket, buffer, 1);
00253                 if (recv <= 0) 
00254                 {
00255                         // For HTTP the socket being closed signifies the end
00256                         // of the transmission and is probably not an error!
00257                         if (len == 0)
00258                         {
00259                                 // If the len is zero then we have been disconnected
00260                                 NetMessagePool::instance()->addToPool(netBuffer);
00261                                 return 0;
00262                         }
00263                         else break;
00264                 }
00265 
00266                 netBuffer->getBuffer().addDataToBuffer(buffer, 1);
00267                 len += 1;
00268                 
00269                 // Check for the end of the HTTP header
00270                 if (len > 4 && dataLen == 0)
00271                 {
00272                         if (netBuffer->getBuffer().getBuffer()[len - 4] == '\r' &&
00273                                 netBuffer->getBuffer().getBuffer()[len - 3] == '\n' &&
00274                                 netBuffer->getBuffer().getBuffer()[len - 2] == '\r' &&
00275                                 netBuffer->getBuffer().getBuffer()[len - 1] == '\n')
00276                         {
00277                                 // We have now found the end of the http header
00278                                 // check if there is any data as well
00279                                 netBuffer->getBuffer().getBuffer()[len - 4] = '\0';
00280                                 char *length = strstr(netBuffer->getBuffer().getBuffer(), "Content-Length: ");
00281                                 if (length)
00282                                 {
00283                                         length += 16;
00284                                         int dl = atoi(length);
00285                                         dataLen = len + dl;
00286                                 }
00287                                 else
00288                                 {
00289                                         // No data, so end at current len
00290                                         dataLen = len;
00291                                 }
00292                                 netBuffer->getBuffer().getBuffer()[len - 4] = '\r';
00293                         }
00294                         
00295                 }
00296                 
00297                 if (len >= dataLen && dataLen != 0) break;
00298         }
00299         NetInterface::getBytesIn() += len;
00300 
00301         // return the new buffer
00302         return netBuffer;
00303 }

Generated on Mon Feb 16 15:14:51 2009 for Scorched3D by  doxygen 1.5.3