packet.cpp

Go to the documentation of this file.
00001 /* $Id: packet.cpp 11777 2008-01-07 14:23:25Z rubidium $ */
00002 
00007 #ifdef ENABLE_NETWORK
00008 
00009 #include "../../stdafx.h"
00010 #include "../../string_func.h"
00011 
00012 #include "packet.h"
00013 
00014 
00015 /* Do not want to include functions.h and all required headers */
00016 extern void NORETURN CDECL error(const char *str, ...);
00017 
00022 Packet::Packet(NetworkSocketHandler *cs)
00023 {
00024   assert(cs != NULL);
00025 
00026   this->cs   = cs;
00027   this->next = NULL;
00028   this->pos  = 0; // We start reading from here
00029   this->size = 0;
00030 }
00031 
00036 Packet::Packet(PacketType type)
00037 {
00038   this->cs                   = NULL;
00039   this->next                 = NULL;
00040 
00041   /* Skip the size so we can write that in before sending the packet */
00042   this->pos                  = 0;
00043   this->size                 = sizeof(PacketSize);
00044   this->buffer[this->size++] = type;
00045 }
00046 
00052 Packet *NetworkSend_Init(PacketType type)
00053 {
00054   Packet *packet = new Packet(type);
00055   /* An error is inplace here, because it simply means we ran out of memory. */
00056   if (packet == NULL) error("Failed to allocate Packet");
00057 
00058   return packet;
00059 }
00060 
00064 void Packet::PrepareToSend()
00065 {
00066   assert(this->cs == NULL && this->next == NULL);
00067 
00068   this->buffer[0] = GB(this->size, 0, 8);
00069   this->buffer[1] = GB(this->size, 8, 8);
00070 
00071   this->pos  = 0; // We start reading from here
00072 }
00073 
00086 void Packet::Send_bool(bool data)
00087 {
00088   this->Send_uint8(data ? 1 : 0);
00089 }
00090 
00091 void Packet::Send_uint8(uint8 data)
00092 {
00093   assert(this->size < sizeof(this->buffer) - sizeof(data));
00094   this->buffer[this->size++] = data;
00095 }
00096 
00097 void Packet::Send_uint16(uint16 data)
00098 {
00099   assert(this->size < sizeof(this->buffer) - sizeof(data));
00100   this->buffer[this->size++] = GB(data, 0, 8);
00101   this->buffer[this->size++] = GB(data, 8, 8);
00102 }
00103 
00104 void Packet::Send_uint32(uint32 data)
00105 {
00106   assert(this->size < sizeof(this->buffer) - sizeof(data));
00107   this->buffer[this->size++] = GB(data,  0, 8);
00108   this->buffer[this->size++] = GB(data,  8, 8);
00109   this->buffer[this->size++] = GB(data, 16, 8);
00110   this->buffer[this->size++] = GB(data, 24, 8);
00111 }
00112 
00113 void Packet::Send_uint64(uint64 data)
00114 {
00115   assert(this->size < sizeof(this->buffer) - sizeof(data));
00116   this->buffer[this->size++] = GB(data,  0, 8);
00117   this->buffer[this->size++] = GB(data,  8, 8);
00118   this->buffer[this->size++] = GB(data, 16, 8);
00119   this->buffer[this->size++] = GB(data, 24, 8);
00120   this->buffer[this->size++] = GB(data, 32, 8);
00121   this->buffer[this->size++] = GB(data, 40, 8);
00122   this->buffer[this->size++] = GB(data, 48, 8);
00123   this->buffer[this->size++] = GB(data, 56, 8);
00124 }
00125 
00131 void Packet::Send_string(const char* data)
00132 {
00133   assert(data != NULL);
00134   /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
00135   assert(this->size + strlen(data) + 1 <= sizeof(this->buffer));
00136   while ((this->buffer[this->size++] = *data++) != '\0') {}
00137 }
00138 
00139 
00148 bool Packet::CanReadFromPacket(uint bytes_to_read)
00149 {
00150   /* Don't allow reading from a quit client/client who send bad data */
00151   if (this->cs->HasClientQuit()) return false;
00152 
00153   /* Check if variable is within packet-size */
00154   if (this->pos + bytes_to_read > this->size) {
00155     this->cs->CloseConnection();
00156     return false;
00157   }
00158 
00159   return true;
00160 }
00161 
00165 void Packet::ReadRawPacketSize()
00166 {
00167   assert(this->cs != NULL && this->next == NULL);
00168   this->size  = (PacketSize)this->buffer[0];
00169   this->size += (PacketSize)this->buffer[1] << 8;
00170 }
00171 
00175 void Packet::PrepareToRead()
00176 {
00177   this->ReadRawPacketSize();
00178 
00179   /* Put the position on the right place */
00180   this->pos = sizeof(PacketSize);
00181 }
00182 
00183 bool Packet::Recv_bool()
00184 {
00185   return this->Recv_uint8() != 0;
00186 }
00187 
00188 uint8 Packet::Recv_uint8()
00189 {
00190   uint8 n;
00191 
00192   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00193 
00194   n = this->buffer[this->pos++];
00195   return n;
00196 }
00197 
00198 uint16 Packet::Recv_uint16()
00199 {
00200   uint16 n;
00201 
00202   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00203 
00204   n  = (uint16)this->buffer[this->pos++];
00205   n += (uint16)this->buffer[this->pos++] << 8;
00206   return n;
00207 }
00208 
00209 uint32 Packet::Recv_uint32()
00210 {
00211   uint32 n;
00212 
00213   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00214 
00215   n  = (uint32)this->buffer[this->pos++];
00216   n += (uint32)this->buffer[this->pos++] << 8;
00217   n += (uint32)this->buffer[this->pos++] << 16;
00218   n += (uint32)this->buffer[this->pos++] << 24;
00219   return n;
00220 }
00221 
00222 uint64 Packet::Recv_uint64()
00223 {
00224   uint64 n;
00225 
00226   if (!this->CanReadFromPacket(sizeof(n))) return 0;
00227 
00228   n  = (uint64)this->buffer[this->pos++];
00229   n += (uint64)this->buffer[this->pos++] << 8;
00230   n += (uint64)this->buffer[this->pos++] << 16;
00231   n += (uint64)this->buffer[this->pos++] << 24;
00232   n += (uint64)this->buffer[this->pos++] << 32;
00233   n += (uint64)this->buffer[this->pos++] << 40;
00234   n += (uint64)this->buffer[this->pos++] << 48;
00235   n += (uint64)this->buffer[this->pos++] << 56;
00236   return n;
00237 }
00238 
00240 void Packet::Recv_string(char *buffer, size_t size)
00241 {
00242   PacketSize pos;
00243   char *bufp = buffer;
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);
00261 }
00262 
00263 #endif /* ENABLE_NETWORK */

Generated on Mon Sep 22 20:34:16 2008 for openttd by  doxygen 1.5.6