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 }
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->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 */

Generated on Wed Dec 30 20:40:03 2009 for OpenTTD by  doxygen 1.5.6