# packet.cpp

Go to the documentation of this file.

    00001 /* $Id: packet.cpp 15626 2009-03-06 01:23:25Z rubidium $ */
    00002
    00007 #ifdef ENABLE_NETWORK
    00008
    00009 #include "../../stdafx.h"
    00010 #include "../../string_func.h"
    00011
    00012 #include "packet.h"
    00013
    00018 Packet::Packet(NetworkSocketHandler *cs)
    00019 {
    00020   assert(cs != NULL);
    00021
    00022   this->cs   = cs;
    00023   this->next = NULL;
    00024   this->pos  = 0; // We start reading from here
    00025   this->size = 0;
    00026 }
    00027
    00032 Packet::Packet(PacketType type)
    00033 {
    00034   this->cs                   = NULL;
    00035   this->next                 = NULL;
    00036
    00037   /* Skip the size so we can write that in before sending the packet */
    00038   this->pos                  = 0;
    00039   this->size                 = sizeof(PacketSize);
    00040   this->buffer[this->size++] = type;
    00041 }
    00042
    00048 Packet *NetworkSend_Init(PacketType type)
    00049 {
    00050   Packet *packet = new Packet(type);
    00051   /* An error is inplace here, because it simply means we ran out of memory. */
    00052   if (packet == NULL) error("Failed to allocate Packet");
    00053
    00054   return packet;
    00055 }
    00056
    00060 void Packet::PrepareToSend()
    00061 {
    00062   assert(this->cs == NULL && this->next == NULL);
    00063
    00064   this->buffer[0] = GB(this->size, 0, 8);
    00065   this->buffer[1] = GB(this->size, 8, 8);
    00066
    00067   this->pos  = 0; // We start reading from here
    00068 }
    00069
    00082 void Packet::Send_bool(bool data)
    00083 {
    00084   this->Send_uint8(data ? 1 : 0);
    00085 }
    00086
    00087 void Packet::Send_uint8(uint8 data)
    00088 {
    00089   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00090   this->buffer[this->size++] = data;
    00091 }
    00092
    00093 void Packet::Send_uint16(uint16 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 }
    00099
    00100 void Packet::Send_uint32(uint32 data)
    00101 {
    00102   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00103   this->buffer[this->size++] = GB(data,  0, 8);
    00104   this->buffer[this->size++] = GB(data,  8, 8);
    00105   this->buffer[this->size++] = GB(data, 16, 8);
    00106   this->buffer[this->size++] = GB(data, 24, 8);
    00107 }
    00108
    00109 void Packet::Send_uint64(uint64 data)
    00110 {
    00111   assert(this->size < sizeof(this->buffer) - sizeof(data));
    00112   this->buffer[this->size++] = GB(data,  0, 8);
    00113   this->buffer[this->size++] = GB(data,  8, 8);
    00114   this->buffer[this->size++] = GB(data, 16, 8);
    00115   this->buffer[this->size++] = GB(data, 24, 8);
    00116   this->buffer[this->size++] = GB(data, 32, 8);
    00117   this->buffer[this->size++] = GB(data, 40, 8);
    00118   this->buffer[this->size++] = GB(data, 48, 8);
    00119   this->buffer[this->size++] = GB(data, 56, 8);
    00120 }
    00121
    00127 void Packet::Send_string(const char *data)
    00128 {
    00129   assert(data != NULL);
    00130   /* The <= *is* valid due to the fact that we are comparing sizes and not the index. */
    00131   assert(this->size + strlen(data) + 1 <= sizeof(this->buffer));
    00132   while ((this->buffer[this->size++] = *data++) != '\0') {}
    00133 }
    00134
    00135
    00144 bool Packet::CanReadFromPacket(uint bytes_to_read)
    00145 {
    00146   /* Don't allow reading from a quit client/client who send bad data */
    00147   if (this->cs->HasClientQuit()) return false;
    00148
    00149   /* Check if variable is within packet-size */
    00150   if (this->pos + bytes_to_read > this->size) {
    00151     this->cs->CloseConnection();
    00152     return false;
    00153   }
    00154
    00155   return true;
    00156 }
    00157
    00161 void Packet::ReadRawPacketSize()
    00162 {
    00163   assert(this->cs != NULL && this->next == NULL);
    00164   this->size  = (PacketSize)this->buffer[0];
    00165   this->size += (PacketSize)this->buffer[1] << 8;
    00166 }
    00167
    00171 void Packet::PrepareToRead()
    00172 {
    00173   this->ReadRawPacketSize();
    00174
    00175   /* Put the position on the right place */
    00176   this->pos = sizeof(PacketSize);
    00177 }
    00178
    00179 bool Packet::Recv_bool()
    00180 {
    00181   return this->Recv_uint8() != 0;
    00182 }
    00183
    00184 uint8 Packet::Recv_uint8()
    00185 {
    00186   uint8 n;
    00187
    00188   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00189
    00190   n = this->buffer[this->pos++];
    00191   return n;
    00192 }
    00193
    00194 uint16 Packet::Recv_uint16()
    00195 {
    00196   uint16 n;
    00197
    00198   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00199
    00200   n  = (uint16)this->buffer[this->pos++];
    00201   n += (uint16)this->buffer[this->pos++] << 8;
    00202   return n;
    00203 }
    00204
    00205 uint32 Packet::Recv_uint32()
    00206 {
    00207   uint32 n;
    00208
    00209   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00210
    00211   n  = (uint32)this->buffer[this->pos++];
    00212   n += (uint32)this->buffer[this->pos++] << 8;
    00213   n += (uint32)this->buffer[this->pos++] << 16;
    00214   n += (uint32)this->buffer[this->pos++] << 24;
    00215   return n;
    00216 }
    00217
    00218 uint64 Packet::Recv_uint64()
    00219 {
    00220   uint64 n;
    00221
    00222   if (!this->CanReadFromPacket(sizeof(n))) return 0;
    00223
    00224   n  = (uint64)this->buffer[this->pos++];
    00225   n += (uint64)this->buffer[this->pos++] << 8;
    00226   n += (uint64)this->buffer[this->pos++] << 16;
    00227   n += (uint64)this->buffer[this->pos++] << 24;
    00228   n += (uint64)this->buffer[this->pos++] << 32;
    00229   n += (uint64)this->buffer[this->pos++] << 40;
    00230   n += (uint64)this->buffer[this->pos++] << 48;
    00231   n += (uint64)this->buffer[this->pos++] << 56;
    00232   return n;
    00233 }
    00234
    00236 void Packet::Recv_string(char *buffer, size_t size, bool allow_newlines)
    00237 {
    00238   PacketSize pos;
    00239   char *bufp = buffer;
    00240   const char *last = buffer + size - 1;
    00241
    00242   /* Don't allow reading from a closed socket */
    00243   if (cs->HasClientQuit()) return;
    00244
    00245   pos = this->pos;
    00246   while (--size > 0 && pos < this->size && (*buffer++ = this->buffer[pos++]) != '\0') {}
    00247
    00248   if (size == 0 || pos == this->size) {
    00249     *buffer = '\0';
    00250     /* If size was sooner to zero then the string in the stream
    00251      *  skip till the \0, so than packet can be read out correctly for the rest */
    00252     while (pos < this->size && this->buffer[pos] != '\0') pos++;
    00253     pos++;
    00254   }
    00255   this->pos = pos;
    00256
    00257   str_validate(bufp, last, allow_newlines);
    00258 }
    00259
    00260 #endif /* ENABLE_NETWORK */