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

Generated on Wed Jul 15 20:35:59 2009 for OpenTTD by  doxygen 1.5.6