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