Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages | Examples

frameworkpacket.h

00001 /***************************************************************************
00002  * The contents of this file are subject to the Mozilla Public             *
00003  * License Version 1.1 (the "License"); you may not use this file          *
00004  * except in compliance with the License. You may obtain a copy of         *
00005  * the License at http://www.mozilla.org/MPL/                              *
00006  *                                                                         *
00007  * Software distributed under the License is distributed on an "AS         *
00008  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
00009  * implied. See the License for the specific language governing            *
00010  * rights and limitations under the License.                               *
00011  *                                                                         *
00012  * The Original Code is Game Network Framework (GaNeF).                    *
00013  *                                                                         *
00014  * The Initial Developers of the Original Code are                         *
00015  * Lars Langer and Emanuel Greisen                                         *
00016  * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
00017  * All Rights Reserved.                                                    *
00018  *                                                                         *
00019  * Contributor(s):                                                         *
00020  *   none yet....                                                          *
00021  *                                                                         *
00022  ***************************************************************************/
00023 #ifndef FRAMEWORKPACKET_H
00024 #define FRAMEWORKPACKET_H
00025 
00026 #include <string>
00027 #include <iostream>
00028 #include <netinet/in.h>
00029 
00030 #include "frameworkdata.h"
00031 
00032 #include <pinet.h>
00033 USING_PTYPES;
00034 
00035 #define INITIAL_BODY_SIZE     256
00036 #define MIN_EXPAND_BODY_SIZE   64
00037 #define MAX_PACKET_SIZE     (65496+sizeof(FrameworkPacket::Header))
00038 
00039 
00040 template<class PacketType,class SocketType>
00041 class Framework;
00042 template<class PacketType, class SocketType>
00043 class PacketSender;
00044 
00045 /**
00046  * @ingroup Common
00047  * @brief This struct is used when throwing packet related exceptions.
00048  */
00049 struct PacketError
00050 {
00051    std::string msg;
00052    PacketError(const std::string & msg) : msg(msg){};
00053 };
00054 
00055 
00056 /**
00057  * @ingroup Common
00058  * @brief This class is a UDP-packet, partly read by the framework, This gives us some knowledge of what is inside the packet.
00059  *
00060  * Here is the format of the packet:
00061 
00062 <table border="1" cellspacing="0">
00063 <tr><th colspan=2>header</th></tr>
00064 <tr><td>[1 unsigned byte]    <td></td>reliable (0: unreliable, 1-255: reliable)</td></tr>
00065 <tr><td>[1 unsigned byte]    <td></td>type (0:system, 1:plugin, 2:new object, 3:detroy object, 4-255: userdefined update of object)</td></tr>
00066 <tr><td>[1 unsigned byte]    <td></td>priority (0: high, 255: low)</td></tr>
00067 <tr><td>[32 bit unsigned int]<td></td>receiver (plugin_id or object_id)</td></tr>
00068 <tr><td>[32 bit unsigned int]<td></td>packet_seq_number: used to determine if a packet should overwrite a new one, and to discard old packets that arrive very late.</td></tr>
00069 <tr><th colspan=2>body</th></tr>
00070 <tr><td>unsigned char[size - sizeof(Header)]</td><td>the actual data</td></tr>
00071 </table>
00072 
00073 @author Lars Langer and Emanuel Greisen
00074 */
00075 class FrameworkPacket
00076 {
00077 friend class PacketSender<class PacketType,class SocketType>;
00078 friend class Framework<class PacketType,class SocketType>;
00079 friend std::ostream & operator <<( std::ostream & o, FrameworkPacket & packet );
00080 
00081 public:
00082    /// This enum is used to keep track of the state of the packet.
00083    enum PacketState
00084    {
00085       /// The packet has just been create (for sending).
00086       STATE_NEW        = 1000,
00087       /// The packet has been queued (for sending).
00088       STATE_QUEUED_OUT = 1001,
00089       /// The packet has been sent (for sending).
00090       STATE_SENT       = 1002,
00091       /// The packet has been aborted (when we should send one of these, it is deleted instead).
00092       STATE_ABORTED    = 1003,
00093 
00094       /// We just received this packet (Receiving side).
00095       STATE_RECEIVED   = 2000,
00096       /// We have queued the packet in the inqueue, ready to be handled in "keepAlive(...)" (Receiving side).
00097       STATE_QUEUED_IN  = 2001,
00098       /// The packet has been delivered to the ClientFramework (Receiving side).
00099       STATE_DELIVERED  = 2002
00100    };
00101 // Data
00102 protected:
00103    /// Pointer to the actual packet data.
00104    char * data;
00105    /// Allocated size of the actual packet data.
00106    unsigned int realsize;
00107    /// The internal position (when reading/writing)
00108    unsigned int pos;
00109    /// True if the packet is incomming, false otherwise
00110    PacketState state;
00111    /// True if the Packet is ready to transmit (htonl/htons).
00112    bool packet_ready_to_transmit;
00113 
00114 public:
00115    /// This holds info about who the message is for or who it is from, depending on `incomming`.
00116    struct PeerStruct
00117    {
00118       ipaddress  host;
00119       int        port;
00120       bool initialized;
00121       PeerStruct() : initialized(false),port(0),host(){};
00122    } peer;
00123 
00124    /// Structure describing the "header" of the packet.
00125    struct Header
00126    {
00127       unsigned char reliable;
00128       unsigned char type;
00129       unsigned char priority;
00130       unsigned int receiver;
00131       unsigned int packet_seq_number;
00132    } ;
00133 protected:
00134    Header * header;
00135 
00136 public:
00137    /// Special constants used when sending system-packets.
00138    enum SpecialReceivers
00139    {
00140       /// May never be sent (only used to write a packet for later appending it to a real packet)
00141       DUMMY_PACKET        =  666,
00142 
00143       /// Used with handshaking.
00144       HANDSHAKE_INIT      = 10001,
00145       /// Used with handshaking.
00146       DISCONTINUE_CLIENT  = 10002,
00147       /// Used with handshaking.
00148       SETUP_DESCRIPTION    = 10003,
00149       /// Used with handshaking.
00150       DISCONTINUE_SERVER   = 10004,
00151       /// Used with handshaking.
00152       READY_CLIENT            = 10005,
00153 
00154       /// An ACK packet.
00155       PACKET_ACK          = 20001,
00156 
00157       /// A Heartbeat packet.
00158       PACKET_HEARTBEAT    = 30001,
00159    };
00160 
00161 protected:
00162    /// Internal constructor: sets everything
00163    FrameworkPacket(unsigned int receiver, unsigned char type=1, unsigned char priority=0, unsigned int bodysize=INITIAL_BODY_SIZE, bool reliable=false);
00164 
00165 public:
00166    /// Constructor used when receiving packets.
00167    FrameworkPacket(char *data, unsigned int size);
00168    /// Destructor, will delete allocated "data" of the packet.
00169    ~FrameworkPacket();
00170 
00171 public:
00172    /// Will copy the data from an other packet, this method relies on the fact that they are duplicates, hence you may not call this method unless the header of the two are identical.
00173    void copyData(FrameworkPacket * packet);
00174 
00175 protected:
00176    /// Will set the position to just after the header (ready for reading/writing)
00177    inline void resetPosition() { pos = sizeof(Header); };
00178    /**
00179     * Will check sanity of read.
00180     * @throws PacketError
00181    **/
00182    void before_read_check(unsigned int s);
00183    /**
00184     * Will check sanity of write.
00185     * @throws PacketError
00186    **/
00187    void before_write_check(unsigned int s);
00188 
00189 public:
00190    /// Used when sending the packet, or receiving.
00191    inline unsigned int getSize() const { return (isIncomming() ? realsize : pos); };
00192    /// Used to get the size of the data only.
00193    inline unsigned int getDataSize() const { return (isIncomming() ? realsize : pos)-sizeof(Header); };
00194    /// Used when sending the packet
00195    inline char * getData() const { return data; };
00196    /// Used when receiving or sending packets.
00197    inline void setPeer(const ipaddress & host, const int port){ peer.host = host; peer.port = port; peer.initialized = true; };
00198    /// Used to reply other packets.
00199    void setPeerFromPacket(FrameworkPacket * packet);
00200 
00201 public:
00202    /// This method makes the packet ready for sending (htonl(...) is called on header fields).
00203    virtual void makeSendReady() = 0;
00204 
00205 public:
00206    /// This sets the sequence number for the packet.
00207    inline void setSequenceNumber(unsigned int seq_no){ header->packet_seq_number = seq_no; };
00208 
00209 
00210 public:
00211    /// @name Header Status Methods
00212    /// These methods are used to check things about what kind of packet this is, a lot of them are just convienent ways of combining checks on the header.
00213    /// @{
00214    /// From header: reliable
00215    inline bool isReliable() const { return (header->reliable != 0); };
00216    /// From header: type
00217    inline unsigned char getType() const { return header->type; };
00218    /// From header: priority
00219    inline unsigned char getPriority() const { return header->priority; };
00220    /// From header: receiver
00221    inline unsigned int getReceiver() const { return packet_ready_to_transmit ? ntohl(header->receiver) : header->receiver; };
00222    /// From header: packet_id
00223    inline unsigned int getSequenceNumber() const { return packet_ready_to_transmit ? ntohl(header->packet_seq_number) : header->packet_seq_number; };
00224    /// true if the packet is incomming
00225    inline bool isIncomming() const { return state >= STATE_RECEIVED; };
00226    /// return true if the packet has left the queue and entered the network.
00227    inline bool hasBeenSent() const { return state == STATE_SENT; };
00228    /// Will return true if the last thing that happened to a packet was insertion into a queue.
00229    inline bool isQueued() const { return state == STATE_QUEUED_IN || state == STATE_QUEUED_OUT; };
00230    /// Will return true if the packet has been aborted (this happens while in the out-queue).
00231    inline bool isAborted() const { return state == STATE_ABORTED; };
00232    /// true if this packet is a plugin-packet
00233    inline bool isPluginPacket() const { return getType() == 1; };
00234    inline bool isHeartBeatPacket() const { return getType() == 0 && getReceiver() == PACKET_HEARTBEAT; };
00235    inline bool isHandshakeInitPacket() const { return getType() == 0 && getReceiver() == HANDSHAKE_INIT; };
00236    /// Will return true if the packet is an ACK-packet
00237    inline bool isAckPacket() const { return getType() == 0 && getReceiver() == PACKET_ACK; };
00238    /// @}
00239 
00240 
00241    /// @name Packet State Methods
00242    /// These will change the state of the packet.
00243    /// @{
00244    void setStateQueued();
00245    void setStateSent();
00246    void setStateAborted();
00247    /// @}
00248 
00249 ///@name Readers
00250 ///@throws PacketError is thrown if you try to read beyond the size of the packet.
00251 /// <p>
00252 /// The following methods are used when reading from a packet.
00253 ///@{
00254 private:
00255    template<typename T>
00256    inline T read()
00257    {
00258       before_read_check(sizeof(T));
00259 
00260       T i = *((T*)&data[pos]);
00261 
00262       pos += sizeof(T);
00263       return i;
00264    };
00265 
00266 public:
00267    int            readInt32();
00268    unsigned int   readUInt32();
00269    short          readInt16();
00270    unsigned short readUInt16();
00271    char           readInt8();
00272    unsigned char  readUInt8();
00273    float          readFloat32();
00274    double         readDouble64();
00275    bool           readBool8();
00276    void           readData(void * dstbuff, unsigned int bytes);
00277    std::string    readString();
00278    ///@}
00279 
00280 ///@name Writers
00281 ///@throws PacketError is thrown if you try to write beyond the hard-coded max-size of the packet.
00282 /// <p>
00283 /// The following methods are used when writing to a packet.
00284 ///@{
00285 private:
00286    template<typename T>
00287    inline void write(const T &v)
00288    {
00289       before_write_check(sizeof(T));
00290 
00291       *((T*)&data[pos]) = v;
00292       pos += sizeof(T);
00293    };
00294 public:
00295    void writeInt32(const int &i);
00296    void writeInt16(const short &i);
00297    void writeInt8(const char &i);
00298    void writeUInt32(const unsigned int &i);
00299    void writeUInt16(const unsigned short &i);
00300    void writeUInt8(const unsigned char &i);
00301    void writeFloat32(const float &f);
00302    void writeDouble64(const double &d);
00303    void writeBool8(const bool &b);
00304    void writeString(const std::string &s);
00305    void writeData(const void * srcdata, unsigned int bytes);
00306    /// Will append the data of the given packet to this packets data, using memcpy(...).
00307    void appendData(FrameworkPacket * packet);
00308    void writePacket(FrameworkPacket * packet);
00309 ///@}
00310 };
00311 
00312 //
00313 // Inline wrappers for the template read method
00314 inline int            FrameworkPacket::readInt32()   { return ntohl(read<int>()); };
00315 inline unsigned int   FrameworkPacket::readUInt32()  { return ntohl(read<unsigned int>()); };
00316 inline short          FrameworkPacket::readInt16()   { return ntohs(read<short>()); };
00317 inline unsigned short FrameworkPacket::readUInt16()  { return ntohs(read<unsigned short>()); };
00318 inline char           FrameworkPacket::readInt8()   { return read<char>(); };
00319 inline unsigned char  FrameworkPacket::readUInt8()  { return read<unsigned char>(); };
00320 inline float          FrameworkPacket::readFloat32() { return read<float>(); };
00321 inline double         FrameworkPacket::readDouble64(){ return read<double>(); };
00322 inline bool           FrameworkPacket::readBool8()   { return read<bool>(); };
00323 
00324 
00325 //
00326 // Inline wrappers for the template write method
00327 inline void FrameworkPacket::writeInt32(const int &i)            { write(htonl(i));};
00328 inline void FrameworkPacket::writeUInt32(const unsigned int &i)  { write(htonl(i));};
00329 inline void FrameworkPacket::writeInt16(const short &i)          { write(htons(i));};
00330 inline void FrameworkPacket::writeUInt16(const unsigned short &i){ write(htons(i));};
00331 inline void FrameworkPacket::writeInt8(const char &i)            { write(i);};
00332 inline void FrameworkPacket::writeUInt8(const unsigned char &i)  { write(i);};
00333 inline void FrameworkPacket::writeFloat32(const float &f)        { write(f);};
00334 inline void FrameworkPacket::writeDouble64(const double &d)      { write(d);};
00335 inline void FrameworkPacket::writeBool8(const bool &b)           { write(b);};
00336 
00337 
00338 /// Just a method for outputting a packet to standard out.
00339 std::ostream & operator<<(std::ostream & o, FrameworkPacket & packet);
00340 
00341 
00342 
00343 #endif

Generated on Mon Feb 6 12:24:50 2006 for Ganef by  doxygen 1.4.4