NetBuffer.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 
00022 #include <net/NetBufferPool.h>
00023 #include <common/Logger.h>
00024 #include <string.h>
00025 #include <zlib.h>
00026 
00027 static const unsigned startSize = 1024 * 10;
00028 
00029 NetBuffer::NetBuffer() : 
00030         buffer_(0),
00031         usedSize_(0),
00032         bufferSize_(0)
00033 {
00034 }
00035 
00036 NetBuffer::NetBuffer(const NetBuffer &other) :
00037         buffer_(0),
00038         usedSize_(0),
00039         bufferSize_(0)  
00040 {
00041         allocate(((NetBuffer &) other).getBufferUsed());
00042         addToBuffer(((NetBuffer &)other).getBuffer());
00043 }
00044 
00045 NetBuffer::NetBuffer(unsigned startSize, void *startBuffer)
00046 {
00047         allocate(startSize);
00048         if (startBuffer)
00049         {
00050                 addDataToBuffer(startBuffer, startSize);
00051         }
00052 }
00053 
00054 NetBuffer::~NetBuffer()
00055 {
00056         delete [] buffer_;
00057         buffer_ = 0;
00058 }
00059 
00060 void NetBuffer::allocate(unsigned size)
00061 {
00062         if (bufferSize_<size)
00063         {
00064                 delete [] buffer_;
00065                 buffer_ = 0;
00066                 buffer_ = new char[size];
00067                 bufferSize_ = size;
00068         }
00069 
00070         usedSize_ = 0;
00071 }
00072 
00073 void NetBuffer::reset()
00074 {
00075         usedSize_ = 0;
00076 }
00077 
00078 void NetBuffer::clear()
00079 {
00080         delete [] buffer_;
00081         usedSize_ = 0;
00082         buffer_ = 0;
00083         bufferSize_ = 0;
00084 }
00085 
00086 bool NetBuffer::compressBuffer()
00087 {
00088         NetBuffer *newBuffer = NetBufferPool::instance()->getFromPool();
00089 
00090         unsigned long destLen = getBufferUsed() * 2;
00091         unsigned long srcLen = getBufferUsed();
00092 
00093         // Compress the message into the new buffer
00094         newBuffer->allocate(destLen);
00095         newBuffer->reset();
00096         newBuffer->addToBuffer((unsigned int) srcLen); // First 4 bytes are for uncompressed size
00097         if (compress2((unsigned char *) (newBuffer->getBuffer() + 4), &destLen, 
00098                                    (unsigned char *) getBuffer(), srcLen, 
00099                                    6) == Z_OK)
00100         {
00101                 newBuffer->setBufferUsed(destLen + 4);
00102 
00103                 // Copy the new buffer into the current buffer
00104                 reset();
00105                 addDataToBuffer(newBuffer->getBuffer(), newBuffer->getBufferUsed());
00106         }
00107 
00108         NetBufferPool::instance()->addToPool(newBuffer);
00109 
00110         return true;
00111 }
00112 
00113 bool NetBuffer::uncompressBuffer()
00114 {
00115         // Get the size of the uncompressed data
00116         NetBufferReader reader(*this);
00117         unsigned int dLen = 0;
00118         if (!reader.getFromBuffer(dLen)) return false;
00119 
00120         // Create a new buffer for the uncompressed data
00121         unsigned long srcLen = getBufferUsed() - 4;
00122         unsigned long destLen = dLen;
00123 
00124 #ifdef S3D_SERVER
00125         if (destLen > 500000)
00126         {
00127                 if (destLen > 2400000)
00128                 {
00129                         Logger::log(S3D::formatStringBuffer("ERROR: Asked to allocated %u bytes", destLen));
00130                         return false;
00131                 }
00132                 else
00133                 {
00134                         Logger::log(S3D::formatStringBuffer("Warning: Asked to allocated %u bytes", destLen));
00135                 }
00136         }
00137 #endif
00138 
00139         NetBuffer *newBuffer = NetBufferPool::instance()->getFromPool();
00140         newBuffer->allocate(destLen);
00141         newBuffer->setBufferUsed(destLen);
00142 
00143         // Uncompress the data
00144         if (uncompress((unsigned char *) newBuffer->getBuffer(), &destLen, 
00145                                    (unsigned char *) (getBuffer() + 4), srcLen) == Z_OK)
00146         {
00147                 // Copy the new buffer into the current buffer
00148                 reset();
00149                 addDataToBuffer(newBuffer->getBuffer(), newBuffer->getBufferUsed());
00150         }
00151         NetBufferPool::instance()->addToPool(newBuffer);
00152 
00153         return true;
00154 }
00155 
00156 void NetBuffer::resize(unsigned newBufferSize)
00157 {
00158         if (newBufferSize < startSize) newBufferSize = startSize;
00159         char *newBuffer = new char[newBufferSize];
00160         if (buffer_)
00161         {
00162                 memcpy(newBuffer, buffer_, usedSize_);
00163                 delete [] buffer_;
00164         }
00165         buffer_ = newBuffer;
00166         bufferSize_ = newBufferSize;
00167 }
00168 
00169 void NetBuffer::addDataToBuffer(const void *add, unsigned len)
00170 {
00171         unsigned bufferLeft = bufferSize_ - usedSize_;
00172         if (!buffer_ || (bufferLeft < len))
00173         {
00174                 unsigned sizeNeeded = len + usedSize_;
00175                 unsigned newBufferSize = sizeNeeded * 2;
00176 
00177                 resize(newBufferSize);
00178         }
00179 
00180         memcpy(&buffer_[usedSize_], add, len);
00181         usedSize_ += len;
00182 }
00183 
00184 void NetBuffer::addToBuffer(Vector &add)
00185 {
00186         addToBuffer(add[0]);
00187         addToBuffer(add[1]);
00188         addToBuffer(add[2]);
00189 }
00190 
00191 void NetBuffer::addToBuffer(FixedVector &add)
00192 {
00193         addToBuffer(add[0]);
00194         addToBuffer(add[1]);
00195         addToBuffer(add[2]);
00196 }
00197 
00198 void NetBuffer::addToBuffer(FixedVector4 &add)
00199 {
00200         addToBuffer(add[0]);
00201         addToBuffer(add[1]);
00202         addToBuffer(add[2]);
00203         addToBuffer(add[3]);
00204 }
00205 
00206 void NetBuffer::addToBuffer(const fixed add)
00207 {
00208         Uint32 value = 0;
00209         SDLNet_Write32(fixed(add).getInternal(), &value);
00210         addDataToBuffer(&value, sizeof(Uint32));
00211 }
00212 
00213 void NetBuffer::addToBuffer(const int add)
00214 {
00215         Uint32 value = 0;
00216         SDLNet_Write32(add, &value);
00217         addDataToBuffer(&value, sizeof(Uint32));
00218 }
00219 
00220 void NetBuffer::addToBuffer(const float addf)
00221 {
00222         Uint32 value = 0;
00223         Uint32 add = 0;
00224         memcpy(&add, &addf, sizeof(Uint32));
00225         SDLNet_Write32(add, &value);
00226         addDataToBuffer(&value, sizeof(Uint32));
00227 }
00228 
00229 void NetBuffer::addToBuffer(const bool add)
00230 {
00231         char c = (add?'1':'0');
00232         addDataToBuffer(&c, sizeof(char));
00233 }
00234 
00235 void NetBuffer::addToBuffer(const char add)
00236 {
00237         addDataToBuffer(&add, sizeof(char));
00238 }
00239 
00240 void NetBuffer::addToBuffer(const unsigned int add)
00241 {
00242         Uint32 value = 0;
00243         SDLNet_Write32(add, &value);
00244         addDataToBuffer(&value, sizeof(Uint32));
00245 }
00246 
00247 void NetBuffer::addToBuffer(const char *add)
00248 {
00249         addDataToBuffer(add, (unsigned) strlen(add)+1);
00250 }
00251 
00252 void NetBuffer::addToBuffer(const std::string &string)
00253 {
00254         addToBuffer(string.c_str());
00255 }
00256 
00257 void NetBuffer::addToBuffer(std::string &string)
00258 {
00259         addToBuffer(string.c_str());
00260 }
00261 
00262 void NetBuffer::addToBuffer(const LangString &string)
00263 {
00264         for (unsigned int i=0; i<=string.size(); i++) 
00265         {
00266                 addToBuffer(string.c_str()[i]);
00267         }
00268 }
00269 
00270 void NetBuffer::addToBuffer(LangString &string)
00271 {
00272         addToBuffer((const LangString &) string);
00273 }
00274 
00275 void NetBuffer::addToBuffer(NetBuffer &add)
00276 {
00277         addToBuffer(add.getBufferUsed());
00278         addDataToBuffer(add.getBuffer(), add.getBufferUsed());
00279 }
00280 
00281 NetBufferReader::NetBufferReader() :
00282         buffer_(0),
00283         bufferSize_(0),
00284         readSize_(0)
00285 {
00286 }
00287 
00288 NetBufferReader::NetBufferReader(NetBuffer &buffer) :
00289         buffer_(buffer.getBuffer()),
00290         bufferSize_(buffer.getBufferUsed()),
00291         readSize_(0)
00292 {
00293 }
00294 
00295 NetBufferReader::~NetBufferReader()
00296 {
00297 }
00298 
00299 void NetBufferReader::reset()
00300 {
00301         readSize_ = 0;
00302 }
00303 
00304 bool NetBufferReader::getFromBuffer(Vector &result)
00305 {
00306         if (!getFromBuffer(result[0])) return false;
00307         if (!getFromBuffer(result[1])) return false;
00308         if (!getFromBuffer(result[2])) return false;
00309         return true;
00310 }
00311 
00312 bool NetBufferReader::getFromBuffer(FixedVector &result)
00313 {
00314         if (!getFromBuffer(result[0])) return false;
00315         if (!getFromBuffer(result[1])) return false;
00316         if (!getFromBuffer(result[2])) return false;
00317         return true;
00318 }
00319 
00320 bool NetBufferReader::getFromBuffer(FixedVector4 &result)
00321 {
00322         if (!getFromBuffer(result[0])) return false;
00323         if (!getFromBuffer(result[1])) return false;
00324         if (!getFromBuffer(result[2])) return false;
00325         if (!getFromBuffer(result[3])) return false;
00326         return true;
00327 }
00328 
00329 bool NetBufferReader::getFromBuffer(int &result)
00330 {
00331         Uint32 value = 0;
00332         if (!getDataFromBuffer(&value, sizeof(value))) return false;
00333         result = SDLNet_Read32(&value);
00334         return true;
00335 }
00336 
00337 bool NetBufferReader::getFromBuffer(fixed &result)
00338 {
00339         Uint32 value = 0;
00340         if (!getDataFromBuffer(&value, sizeof(value))) return false;
00341         result = fixed(true, SDLNet_Read32(&value));
00342         return true;
00343 }
00344 
00345 bool NetBufferReader::getFromBuffer(float &resultf)
00346 {
00347         Uint32 value = 0;
00348         if (!getDataFromBuffer(&value, sizeof(value))) return false;
00349         Uint32 result = SDLNet_Read32(&value);
00350         memcpy(&resultf, &result, sizeof(Uint32));
00351         return true;
00352 }
00353 
00354 bool NetBufferReader::getFromBuffer(bool &result)
00355 {
00356         char c = 0;
00357         if (!getDataFromBuffer(&c, sizeof(c))) return false;
00358         result = (c=='1'?true:false);
00359         return true;
00360 }
00361 
00362 bool NetBufferReader::getFromBuffer(char &result)
00363 {
00364         if (!getDataFromBuffer(&result, sizeof(result))) return false;
00365         return true;
00366 }
00367 
00368 bool NetBufferReader::getFromBuffer(unsigned int &result)
00369 {
00370         Uint32 value = 0;
00371         if (!getDataFromBuffer(&value, sizeof(value))) return false;
00372         result = SDLNet_Read32(&value);
00373         return true;
00374 }
00375 
00376 bool NetBufferReader::getFromBuffer(std::string &result, bool safe)
00377 {
00378         int i;
00379         for (i=0; buffer_[readSize_ + i]; i++);
00380         i++;
00381 
00382         char *value = new char[i+1]; // Another one just in case
00383         if (getDataFromBuffer(value, i))
00384         {
00385                 if (safe)
00386                 {
00387                         for (int j=0; j<i; j++)
00388                         {
00389                                 if (value[j] == '%') value[j] = ' ';
00390                         }
00391                 }
00392 
00393                 result = value;
00394                 delete [] value;
00395 
00396                 return true;
00397         }
00398 
00399         delete [] value;
00400         return false;
00401 }
00402 
00403 bool NetBufferReader::getFromBuffer(LangString &result)
00404 {
00405         result.clear();
00406         unsigned int value = 0;
00407         for (;;) 
00408         {
00409                 if (!getFromBuffer(value)) return false;
00410                 if (!value) break;
00411                 result.push_back(value);
00412         } 
00413 
00414         return true;
00415 }
00416 
00417 bool NetBufferReader::getFromBuffer(NetBuffer &buffer)
00418 {
00419         buffer.reset();
00420         unsigned int bufferSize = 0;
00421         if (!getFromBuffer(bufferSize)) return false;
00422         buffer.resize(bufferSize);
00423         buffer.setBufferUsed(bufferSize);
00424         return getDataFromBuffer(buffer.getBuffer(), bufferSize);
00425 }
00426 
00427 bool NetBufferReader::getDataFromBuffer(void *dest, int len)
00428 {
00429         unsigned bufferLeft = bufferSize_ - readSize_;
00430         if (bufferLeft < (unsigned) len) return false;
00431 
00432         memcpy(dest, &buffer_[readSize_], len);
00433         readSize_ += len;
00434         return true;
00435 }

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