# packet.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    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
    00073 /*
    00074  * The next couple of functions make sure we can send
    00075  *  uint8, uint16, uint32 and uint64 endian-safe
    00076  *  over the network. The least significant bytes are
    00077  *  sent first.
    00078  *
    00079  *  So 0x01234567 would be sent as 67 45 23 01.
    00080  *
    00081  * A bool is sent as a uint8 where zero means false
    00082  *  and non-zero means true.
    00083  */
    00084
    00089 void Packet::Send_bool(bool data)
    00090 {
    00091   this->Send_uint8(data ? 1 : 0);
    00092 }
    00093
    00098 void Packet::Send_uint8(uint8 data)
    00099 {
    00100   assert(this->size < SEND_MTU - sizeof(data));
    00101   this->buffer[this->size++] = data;
    00102 }
    00103
    00108 void Packet::Send_uint16(uint16 data)
    00109 {
    00110   assert(this->size < SEND_MTU - sizeof(data));
    00111   this->buffer[this->size++] = GB(data, 0, 8);
    00112   this->buffer[this->size++] = GB(data, 8, 8);
    00113 }
    00114
    00119 void Packet::Send_uint32(uint32 data)
    00120 {
    00121   assert(this->size < SEND_MTU - sizeof(data));
    00122   this->buffer[this->size++] = GB(data,  0, 8);
    00123   this->buffer[this->size++] = GB(data,  8, 8);
    00124   this->buffer[this->size++] = GB(data, 16, 8);
    00125   this->buffer[this->size++] = GB(data, 24, 8);
    00126 }
    00127
    00132 void Packet::Send_uint64(uint64 data)
    00133 {
    00134   assert(this->size < SEND_MTU - sizeof(data));
    00135   this->buffer[this->size++] = GB(data,  0, 8);
    00136   this->buffer[this->size++] = GB(data,  8, 8);
    00137   this->buffer[this->size++] = GB(data, 16, 8);
    00138   this->buffer[this->size++] = GB(data, 24, 8);
    00139   this->buffer[this->size++] = GB(data, 32, 8);
    00140   this->buffer[this->size++] = GB(data, 40, 8);
    00141   this->buffer[this->size++] = GB(data, 48, 8);
    00142   this->buffer[this->size++] = GB(data, 56, 8);
    00143 }
    00144
    00150 void Packet::Send_string(const char *data)
    00151 {
    00152   assert(data != NULL);
    00153   /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
    00154   assert(this->size + strlen(data) + 1 <= SEND_MTU);
    00155   while ((this->buffer[this->size++] = *data++) != '\0') {}
    00156 }
    00157
    00158
    00159 /*
    00160  * Receiving commands
    00161  * Again, the next couple of functions are endian-safe
    00162  *  see the comment before Send_bool for more info.
    00163  */
    00164
    00165
    00171 bool Packet::CanReadFromPacket(uint bytes_to_read)
    00172 {
    00173   /* Don't allow reading from a quit client/client who send bad data */
    00174   if (this->cs->HasClientQuit()) return false;
    00175
    00176   /* Check if variable is within packet-size */
    00177   if (this->pos + bytes_to_read > this->size) {
    00178     this->cs->NetworkSocketHandler::CloseConnection();
    00179     return false;
    00180   }
    00181
    00182   return true;
    00183 }
    00184
    00188 void Packet::ReadRawPacketSize()
    00189 {
    00190   assert(this->cs != NULL && this->next == NULL);
    00191   this->size  = (PacketSize)this->buffer[0];
    00192   this->size += (PacketSize)this->buffer[1] << 8;
    00193 }
    00194
    00198 void Packet::PrepareToRead()
    00199 {
    00200   this->ReadRawPacketSize();
    00201
    00202   /* Put the position on the right place */
    00203   this->pos = sizeof(PacketSize);
    00204 }
    00205
    00210 bool Packet::Recv_bool()
    00211 {
    00212   return this->Recv_uint8() != 0;
    00213 }
    00214
    00219 uint8 Packet::Recv_uint8()
    00220 {
    00221   uint8 n;
    00222
    00223   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00224
    00225   n = this->buffer[this->pos++];
    00226   return n;
    00227 }
    00228
    00233 uint16 Packet::Recv_uint16()
    00234 {
    00235   uint16 n;
    00236
    00237   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00238
    00239   n  = (uint16)this->buffer[this->pos++];
    00240   n += (uint16)this->buffer[this->pos++] << 8;
    00241   return n;
    00242 }
    00243
    00248 uint32 Packet::Recv_uint32()
    00249 {
    00250   uint32 n;
    00251
    00252   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00253
    00254   n  = (uint32)this->buffer[this->pos++];
    00255   n += (uint32)this->buffer[this->pos++] << 8;
    00256   n += (uint32)this->buffer[this->pos++] << 16;
    00257   n += (uint32)this->buffer[this->pos++] << 24;
    00258   return n;
    00259 }
    00260
    00265 uint64 Packet::Recv_uint64()
    00266 {
    00267   uint64 n;
    00268
    00269   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00270
    00271   n  = (uint64)this->buffer[this->pos++];
    00272   n += (uint64)this->buffer[this->pos++] << 8;
    00273   n += (uint64)this->buffer[this->pos++] << 16;
    00274   n += (uint64)this->buffer[this->pos++] << 24;
    00275   n += (uint64)this->buffer[this->pos++] << 32;
    00276   n += (uint64)this->buffer[this->pos++] << 40;
    00277   n += (uint64)this->buffer[this->pos++] << 48;
    00278   n += (uint64)this->buffer[this->pos++] << 56;
    00279   return n;
    00280 }
    00281
    00288 void Packet::Recv_string(char *buffer, size_t size, StringValidationSettings settings)
    00289 {
    00290   PacketSize pos;
    00291   char *bufp = buffer;
    00292   const char *last = buffer + size - 1;
    00293
    00294   /* Don't allow reading from a closed socket */
    00295   if (cs->HasClientQuit()) return;
    00296
    00297   pos = this->pos;
    00298   while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
    00299
    00300   if (size == 0 || pos == this->size) {
    00301     *buffer = '\0';
    00302     /* If size was sooner to zero then the string in the stream
    00303      *  skip till the \0, so than packet can be read out correctly for the rest */
    00304     while (pos < this->size && this->buffer[pos] != '\0') pos++;
    00305     pos++;
    00306   }
    00307   this->pos = pos;
    00308
    00309   str_validate(bufp, last, settings);
    00310 }
    00311
    00312 #endif /* ENABLE_NETWORK */