packet.cpp

Go to the documentation of this file.
00001 /* $Id: packet.cpp 21357 2010-11-30 13:22:29Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00014 #ifdef ENABLE_NETWORK
00015 
00016 #include "../../stdafx.h"
00017 #include "../../string_func.h"
00018 
00019 #include "packet.h"
00020 
00025 Packet::Packet(NetworkSocketHandler *cs)
00026 {
00027   assert(cs != NULL);
00028 
00029   this->cs     = cs;
00030   this->next   = NULL;
00031   this->pos    = 0; // We start reading from here
00032   this->size   = 0;
00033   this->buffer = MallocT<byte>(SEND_MTU);
00034 }
00035 
00040 Packet::Packet(PacketType type)
00041 {
00042   this->cs                   = NULL;
00043   this->next                 = NULL;
00044 
00045   /* Skip the size so we can write that in before sending the packet */
00046   this->pos                  = 0;
00047   this->size                 = sizeof(PacketSize);
00048   this->buffer               = MallocT<byte>(SEND_MTU);
00049   this->buffer[this->size++] = type;
00050 }
00051 
00055 Packet::~Packet()
00056 {
00057   free(this->buffer);
00058 }
00059 
00063 void Packet::PrepareToSend()
00064 {
00065   assert(this->cs == NULL && this->next == NULL);
00066 
00067   this->buffer[0] = GB(this->size, 0, 8);
00068   this->buffer[1] = GB(this->size, 8, 8);
00069 
00070   this->pos  = 0; // We start reading from here
00071 }
00072 
00085 void Packet::Send_bool(bool data)
00086 {
00087   this->Send_uint8(data ? 1 : 0);
00088 }
00089 
00090 void Packet::Send_uint8(uint8 data)
00091 {
00092   assert(this->size < SEND_MTU - sizeof(data));
00093   this->buffer[this->size++] = data;
00094 }
00095 
00096 void Packet::Send_uint16(uint16 data)
00097 {
00098   assert(this->size < SEND_MTU - sizeof(data));
00099   this->buffer[this->size++] = GB(data, 0, 8);
00100   this->buffer[this->size++] = GB(data, 8, 8);
00101 }
00102 
00103 void Packet::Send_uint32(uint32 data)
00104 {
00105   assert(this->size < SEND_MTU - sizeof(data));
00106   this->buffer[this->size++] = GB(data,  0, 8);
00107   this->buffer[this->size++] = GB(data,  8, 8);
00108   this->buffer[this->size++] = GB(data, 16, 8);
00109   this->buffer[this->size++] = GB(data, 24, 8);
00110 }
00111 
00112 void Packet::Send_uint64(uint64 data)
00113 {
00114   assert(this->size < SEND_MTU - sizeof(data));
00115   this->buffer[this->size++] = GB(data,  0, 8);
00116   this->buffer[this->size++] = GB(data,  8, 8);
00117   this->buffer[this->size++] = GB(data, 16, 8);
00118   this->buffer[this->size++] = GB(data, 24, 8);
00119   this->buffer[this->size++] = GB(data, 32, 8);
00120   this->buffer[this->size++] = GB(data, 40, 8);
00121   this->buffer[this->size++] = GB(data, 48, 8);
00122   this->buffer[this->size++] = GB(data, 56, 8);
00123 }
00124 
00130 void Packet::Send_string(const char *data)
00131 {
00132   assert(data != NULL);
00133   /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
00134   assert(this->size + strlen(data) + 1 <= SEND_MTU);
00135   while ((this->buffer[this->size++] = *data++) != '\0') {}
00136 }
00137 
00138 
00147 bool Packet::CanReadFromPacket(uint bytes_to_read)
00148 {
00149   /* Don't allow reading from a quit client/client who send bad data */
00150   if (this->cs->HasClientQuit()) return false;
00151 
00152   /* Check if variable is within packet-size */
00153   if (this->pos + bytes_to_read > this->size) {
00154     this->cs->NetworkSocketHandler::CloseConnection();
00155     return false;
00156   }
00157 
00158   return true;
00159 }
00160 
00164 void Packet::ReadRawPacketSize()
00165 {
00166   assert(this->cs != NULL && this->next == NULL);
00167   this->size  = (PacketSize)this->buffer[0];
00168   this->size += (PacketSize)this->buffer[1] << 8;
00169 }
00170 
00174 void Packet::PrepareToRead()
00175 {
00176   this->ReadRawPacketSize();
00177 
00178   /* Put the position on the right place */
00179   this->pos = sizeof(PacketSize);
00180 }
00181 
00182 bool Packet::Recv_bool()
00183 {
00184   return this->Recv_uint8() != 0;
00185 }
00186 
00187 uint8 Packet::Recv_uint8()
00188 {
00189   uint8 n;
00190 
00191   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00192 
00193   n = this->buffer[this->pos++];
00194   return n;
00195 }
00196 
00197 uint16 Packet::Recv_uint16()
00198 {
00199   uint16 n;
00200 
00201   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00202 
00203   n  = (uint16)this->buffer[this->pos++];
00204   n += (uint16)this->buffer[this->pos++] << 8;
00205   return n;
00206 }
00207 
00208 uint32 Packet::Recv_uint32()
00209 {
00210   uint32 n;
00211 
00212   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00213 
00214   n  = (uint32)this->buffer[this->pos++];
00215   n += (uint32)this->buffer[this->pos++] << 8;
00216   n += (uint32)this->buffer[this->pos++] << 16;
00217   n += (uint32)this->buffer[this->pos++] << 24;
00218   return n;
00219 }
00220 
00221 uint64 Packet::Recv_uint64()
00222 {
00223   uint64 n;
00224 
00225   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00226 
00227   n  = (uint64)this->buffer[this->pos++];
00228   n += (uint64)this->buffer[this->pos++] << 8;
00229   n += (uint64)this->buffer[this->pos++] << 16;
00230   n += (uint64)this->buffer[this->pos++] << 24;
00231   n += (uint64)this->buffer[this->pos++] << 32;
00232   n += (uint64)this->buffer[this->pos++] << 40;
00233   n += (uint64)this->buffer[this->pos++] << 48;
00234   n += (uint64)this->buffer[this->pos++] << 56;
00235   return n;
00236 }
00237 
00239 void Packet::Recv_string(char *buffer, size_t size, bool allow_newlines)
00240 {
00241   PacketSize pos;
00242   char *bufp = buffer;
00243   const char *last = buffer + size - 1;
00244 
00245   /* Don't allow reading from a closed socket */
00246   if (cs->HasClientQuit()) return;
00247 
00248   pos = this->pos;
00249   while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
00250 
00251   if (size == 0 || pos == this->size) {
00252     *buffer = '\0';
00253     /* If size was sooner to zero then the string in the stream
00254      *  skip till the \0, so than packet can be read out correctly for the rest */
00255     while (pos < this->size && this->buffer[pos] != '\0') pos++;
00256     pos++;
00257   }
00258   this->pos = pos;
00259 
00260   str_validate(bufp, last, allow_newlines);
00261 }
00262 
00263 #endif /* ENABLE_NETWORK */

Generated on Fri Mar 18 23:17:37 2011 for OpenTTD by  doxygen 1.6.1