# packet.cpp

Go to the documentation of this file.

    00001 /* $Id: packet.cpp 18800 2010-01-14 21:47:31Z 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 }
    00034
    00039 Packet::Packet(PacketType type)
    00040 {
    00041   this->cs                   = NULL;
    00042   this->next                 = NULL;
    00043
    00044   /* Skip the size so we can write that in before sending the packet */
    00045   this->pos                  = 0;
    00046   this->size                 = sizeof(PacketSize);
    00047   this->buffer[this->size++] = type;
    00048 }
    00049
    00053 void Packet::PrepareToSend()
    00054 {
    00055   assert(this->cs == NULL && this->next == NULL);
    00056
    00057   this->buffer[0] = GB(this->size, 0, 8);
    00058   this->buffer[1] = GB(this->size, 8, 8);
    00059
    00060   this->pos  = 0; // We start reading from here
    00061 }
    00062
    00075 void Packet::Send_bool(bool data)
    00076 {
    00077   this->Send_uint8(data ? 1 : 0);
    00078 }
    00079
    00080 void Packet::Send_uint8(uint8 data)
    00081 {
    00082   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00083   this->buffer[this->size++] = data;
    00084 }
    00085
    00086 void Packet::Send_uint16(uint16 data)
    00087 {
    00088   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00089   this->buffer[this->size++] = GB(data, 0, 8);
    00090   this->buffer[this->size++] = GB(data, 8, 8);
    00091 }
    00092
    00093 void Packet::Send_uint32(uint32 data)
    00094 {
    00095   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00096   this->buffer[this->size++] = GB(data,  0, 8);
    00097   this->buffer[this->size++] = GB(data,  8, 8);
    00098   this->buffer[this->size++] = GB(data, 16, 8);
    00099   this->buffer[this->size++] = GB(data, 24, 8);
    00100 }
    00101
    00102 void Packet::Send_uint64(uint64 data)
    00103 {
    00104   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00105   this->buffer[this->size++] = GB(data,  0, 8);
    00106   this->buffer[this->size++] = GB(data,  8, 8);
    00107   this->buffer[this->size++] = GB(data, 16, 8);
    00108   this->buffer[this->size++] = GB(data, 24, 8);
    00109   this->buffer[this->size++] = GB(data, 32, 8);
    00110   this->buffer[this->size++] = GB(data, 40, 8);
    00111   this->buffer[this->size++] = GB(data, 48, 8);
    00112   this->buffer[this->size++] = GB(data, 56, 8);
    00113 }
    00114
    00120 void Packet::Send_string(const char *data)
    00121 {
    00122   assert(data != NULL);
    00123   /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
    00124   assert(this->size + strlen(data) + 1 <= sizeof(this->buffer));
    00125   while ((this->buffer[this->size++] = *data++) != '\0') {}
    00126 }
    00127
    00128
    00137 bool Packet::CanReadFromPacket(uint bytes_to_read)
    00138 {
    00139   /* Don't allow reading from a quit client/client who send bad data */
    00140   if (this->cs->HasClientQuit()) return false;
    00141
    00142   /* Check if variable is within packet-size */
    00143   if (this->pos + bytes_to_read > this->size) {
    00144     this->cs->NetworkSocketHandler::CloseConnection();
    00145     return false;
    00146   }
    00147
    00148   return true;
    00149 }
    00150
    00154 void Packet::ReadRawPacketSize()
    00155 {
    00156   assert(this->cs != NULL && this->next == NULL);
    00157   this->size  = (PacketSize)this->buffer[0];
    00158   this->size += (PacketSize)this->buffer[1] << 8;
    00159 }
    00160
    00164 void Packet::PrepareToRead()
    00165 {
    00166   this->ReadRawPacketSize();
    00167
    00168   /* Put the position on the right place */
    00169   this->pos = sizeof(PacketSize);
    00170 }
    00171
    00172 bool Packet::Recv_bool()
    00173 {
    00174   return this->Recv_uint8() != 0;
    00175 }
    00176
    00177 uint8 Packet::Recv_uint8()
    00178 {
    00179   uint8 n;
    00180
    00181   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00182
    00183   n = this->buffer[this->pos++];
    00184   return n;
    00185 }
    00186
    00187 uint16 Packet::Recv_uint16()
    00188 {
    00189   uint16 n;
    00190
    00191   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00192
    00193   n  = (uint16)this->buffer[this->pos++];
    00194   n += (uint16)this->buffer[this->pos++] << 8;
    00195   return n;
    00196 }
    00197
    00198 uint32 Packet::Recv_uint32()
    00199 {
    00200   uint32 n;
    00201
    00202   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00203
    00204   n  = (uint32)this->buffer[this->pos++];
    00205   n += (uint32)this->buffer[this->pos++] << 8;
    00206   n += (uint32)this->buffer[this->pos++] << 16;
    00207   n += (uint32)this->buffer[this->pos++] << 24;
    00208   return n;
    00209 }
    00210
    00211 uint64 Packet::Recv_uint64()
    00212 {
    00213   uint64 n;
    00214
    00215   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00216
    00217   n  = (uint64)this->buffer[this->pos++];
    00218   n += (uint64)this->buffer[this->pos++] << 8;
    00219   n += (uint64)this->buffer[this->pos++] << 16;
    00220   n += (uint64)this->buffer[this->pos++] << 24;
    00221   n += (uint64)this->buffer[this->pos++] << 32;
    00222   n += (uint64)this->buffer[this->pos++] << 40;
    00223   n += (uint64)this->buffer[this->pos++] << 48;
    00224   n += (uint64)this->buffer[this->pos++] << 56;
    00225   return n;
    00226 }
    00227
    00229 void Packet::Recv_string(char *buffer, size_t size, bool allow_newlines)
    00230 {
    00231   PacketSize pos;
    00232   char *bufp = buffer;
    00233   const char *last = buffer + size - 1;
    00234
    00235   /* Don't allow reading from a closed socket */
    00236   if (cs->HasClientQuit()) return;
    00237
    00238   pos = this->pos;
    00239   while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
    00240
    00241   if (size == 0 || pos == this->size) {
    00242     *buffer = '\0';
    00243     /* If size was sooner to zero then the string in the stream
    00244      *  skip till the \0, so than packet can be read out correctly for the rest */
    00245     while (pos < this->size && this->buffer[pos] != '\0') pos++;
    00246     pos++;
    00247   }
    00248   this->pos = pos;
    00249
    00250   str_validate(bufp, last, allow_newlines);
    00251 }
    00252
    00253 #endif /* ENABLE_NETWORK */