| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /* Copyright The kNet Project.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License. */
- #pragma once
- /** @file NetworkMessage.h
- @brief The class NetworkMessage. Stores an outbound network message. */
- #include "kNetBuildConfig.h"
- #include "LockFreePoolAllocator.h"
- #include "FragmentedTransferManager.h"
- #include "Types.h"
- namespace kNet
- {
- /// Performs modular arithmetic comparison to see if newID refers to a PacketID that is *strictly* newer than oldID.
- /// @return True if newID is *strictly* newer than oldID, false otherwise.
- inline bool PacketIDIsNewerThan(packet_id_t newID, packet_id_t oldID)
- {
- packet_id_t diff = (packet_id_t)(newID - oldID);
- packet_id_t diff2 = (packet_id_t)(newID + 0x3FFFFF - oldID);
- return diff < 0x1FFFFF || diff2 < 0x1FFFFF;
- }
- /// Computes the PacketID for the packet (id + increment).
- inline packet_id_t AddPacketID(packet_id_t id, int increment)
- {
- return (id + increment) & ((1 << 22) - 1);
- }
- /// Computes the PacketID for the packet (id - sub).
- inline packet_id_t SubPacketID(packet_id_t id, int sub)
- {
- if ((int)id >= sub)
- return (packet_id_t)(id - sub);
- else
- return (packet_id_t)((1 << 22) - (sub-id));
- }
- /// NetworkMessage stores the serialized byte data of a single outbound network message, along
- /// with fields that specify how itreated by the network connection.
- class NetworkMessage : public PoolAllocatable<NetworkMessage>
- {
- public:
- /// To create a NetworkMessage, call MessageConnection::StartNewMessage() instead of directly instantiating
- /// a message structure. This is because each MessageConnection implements an internal pool of NetworkMessage
- /// structures which are reused between messages, to avoid excessive dynamic memory allocation.
- NetworkMessage();
- NetworkMessage &operator=(const NetworkMessage &rhs);
- NetworkMessage(const NetworkMessage &rhs);
- ~NetworkMessage();
- /// Stores the actual data of the message.
- /// When writing a new message, fill in the data bytes here. This buffer can hold Capacity() amount of bytes. If you need more,
- /// call Reallocate() with the desired amount of bytes.
- /// This field is read-only, do not change this pointer value.
- char *data;
- size_t Capacity() const { return dataCapacity; }
- size_t Size() const { return dataSize; }
- /// Resizes the message to the given amount of bytes. Reallocates the data buffer if it cannot fit into the new size.
- /// @param newBytes The new amount of bytes to use for the message.
- /// @param discard If true, any existing partially filled data will not be copied over, but the new buffer will have its
- /// bytes left uninitialized. If false, this function preserves any old partially filled data and works
- /// like std::vector::resize(). The intended purpose of this function is to be called prior to filling
- /// in any data, and so the default value is true.
- void Resize(size_t newBytes, bool discard = true);
- /// The send priority of this message with respect to other messages. Priority 0 is the lowest, and
- /// priority 0xFFFFFFFE is the highest. Priority 0xFFFFFFFF is a special one that means 'don't send this message'.
- unsigned long priority;
- /// The ID of this message. IDs 0 - 5 are reserved for the protocol and may not be used.
- /// Valid user range is [6, 1073741821 == 0x3FFFFFFD].
- message_id_t id;
- /// When sending out a message, the application can attach a content ID to the message,
- /// which will effectively replace all the older messages with the same messageID and
- /// contentID.
- unsigned long contentID;
- /// If true, this message should be delivered reliably, possibly resent to guarantee
- /// that the receiving party gets it.
- bool reliable;
- /// If true, this message should be delivered in-order with all the other in-order
- /// messages. The processing order of this message relative to non-in-ordered messages
- /// is not specified and can vary.
- bool inOrder;
- /// If this flag is set, the message will not be sent and will be deleted as soon
- /// as possible. It has been superceded by another message before it had the time
- /// to leave the outbound send queue.
- bool obsolete;
- #ifdef KNET_NETWORK_PROFILING
- std::string profilerName;
- #endif
- /// Checks if this message is newer than the other message.
- bool IsNewerThan(const NetworkMessage &rhs) const { return (unsigned long)(messageNumber - rhs.messageNumber) < 0x80000000; }
- /// A message with this priority is obsolete and should not be sent through the connection.
- static const unsigned long cPriorityDontSend = 0xFFFFFFFF;
- /// The maximum priority a message can have.
- static const unsigned long cMaxPriority = 0xFFFFFFFE;
- /// Returns the total number of bytes this datagram will take up space when it is serialized to an UDP channel.
- int GetTotalDatagramPackedSize() const;
- /// Returns the number of this message. The message number identifies the admission order of messages to the outbound queue.
- unsigned long MessageNumber() const { return messageNumber; }
- private:
- friend class MessageConnection;
- friend class UDPMessageConnection;
- friend class TCPMessageConnection;
- friend class FragmentedSendManager;
- friend struct FragmentedSendManager::FragmentedTransfer;
- /// A temporary storage area to remember the UDP packet ID this messages was received in.
- /// For TCP messages, this field is always zero.
- /// When sending out messages, this field is not used.
- packet_id_t receivedPacketID;
- /// A running number that is assigned to each message to distinguish the order
- /// the messages were added to the queue. The network layer manages this numbering,
- /// the application can not control it. This is used to break ties on packets
- /// that have the same priority.
- unsigned long messageNumber;
- /// A running number that is assigned to each reliable message. This is used in the
- /// network byte stream to implement ordering of messages.
- unsigned long reliableMessageNumber;
- /// The number of times this message has been sent and not been acked (reliable messages only).
- unsigned long sendCount;
- /// The index of this fragment, or not used (undefined) if totalNumFragments==0.
- unsigned long fragmentIndex;
- /// Tells the number of bytes that have been allocated and can be filled to the data array.
- size_t dataCapacity;
- /// Specifies the number of bytes actually used in the data array.
- size_t dataSize;
- /// If 0, this message is being sent unfragmented. Otherwise, this NetworkMessage is a fragment of the whole
- /// message and transfer points to the data structure that tracks the transfer of a fragmented message.
- FragmentedSendManager::FragmentedTransfer *transfer;
- };
- } // ~kNet
|