Files
src-1.2/external/3rd/library/soePlatform/ChatAPI/utils/UdpLibrary/UdpConnection.h
T

727 lines
35 KiB
C++
Executable File

#ifndef UDPLIBRARY_UDPCONNECTION_H
#define UDPLIBRARY_UDPCONNECTION_H
// Copyright 2004 Sony Online Entertainment, all rights reserved.
// Author: Jeff Petersen
namespace UdpLibrary
{
class UdpReliableChannel;
struct UdpConnectionStatistics
{
/////////////////////////////////////////////////////////////////////////
// these statistics are valid even if clock-sync is not used
// these statistics are never reset and should not be as the negotiated
// packetloss stats would get messed up if they were
// as such, use UdpConnection::ConnectionAge to determine how long they have been accumulating
/////////////////////////////////////////////////////////////////////////
udp_int64 totalBytesSent;
udp_int64 totalBytesReceived;
udp_int64 totalPacketsSent; // total packets we have sent
udp_int64 totalPacketsReceived; // total packets we have received
udp_int64 crcRejectedPackets; // total packets on our connection that have been rejected due to a crc error
udp_int64 orderRejectedPackets; // total packets on our connection that have been rejected due to an order error (only applicable for ordered channel)
udp_int64 duplicatePacketsReceived; // total reliable packets that we received where we had already received it before and threw it away
udp_int64 resentPacketsAccelerated; // number of times we have resent a packet due to receiving a later packet in the series
udp_int64 resentPacketsTimedOut; // number of times we have resent a packet due to the ack-timeout expiring
udp_int64 applicationPacketsSent;
udp_int64 applicationPacketsReceived;
udp_int64 iterations; // number of times this connection has been given processing time
udp_int64 corruptPacketErrors; // number of misformed/corrupt packets
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// these statistics are only valid if clock-sync'ing is enabled (highly recommended) (will be valid on both client and server side)
// these statistics are reset by PingStatReset and are negotiated periodically by the clock-sync stuff (Params::clockSyncDelay)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int masterPingAge; // only valid (and applicable) on client side
int masterPingTime;
int averagePingTime;
int lowPingTime;
int highPingTime;
int lastPingTime;
int reliableAveragePing; // the average time (over last 3 acks) for a reliable packet to get acked (when packet is not lost)
udp_int64 syncOurSent; // total packets we have sent at time they reported their numbers
udp_int64 syncOurReceived; // total packets we have received at time they reported their numbers
udp_int64 syncTheirSent; // total packets they have sent
udp_int64 syncTheirReceived; // total packets they have received
float percentSentSuccess;
float percentReceivedSuccess;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The purpose of the UdpConnection is to manage a single logical connection
////////////////////////////////////////////////////////////////////////////////////////////////////////////
class UdpConnection : public UdpGuardedRefCount, public PriorityQueueMember, public HashTableMember1<UdpConnection>, public HashTableMember2<UdpConnection>
{
public:
enum Status { cStatusNegotiating, cStatusConnected, cStatusDisconnected, cStatusDisconnectPending, cStatusCount };
enum DisconnectReason { cDisconnectReasonNone, cDisconnectReasonIcmpError, cDisconnectReasonTimeout
, cDisconnectReasonOtherSideTerminated, cDisconnectReasonManagerDeleted
, cDisconnectReasonConnectFail, cDisconnectReasonApplication
, cDisconnectReasonUnreachableConnection, cDisconnectReasonUnacknowledgedTimeout
, cDisconnectReasonNewConnectionAttempt, cDisconnectReasonConnectionRefused
, cDisconnectReasonMutualConnectError, cDisconnectReasonConnectingToSelf
, cDisconnectReasonReliableOverflow, cDisconnectReasonApplicationReleased
, cDisconnectReasonCorruptPacket
, cDisconnectReasonCount };
// returns the current status of this connection
Status GetStatus() const;
// returns the reason that a connection was disconnected. See the enum above for a list of all the reasons
DisconnectReason GetDisconnectReason() const;
char *GetDisconnectReasonText(char *buf, int bufLen) const;
DisconnectReason GetOtherSideDisconnectReason() const;
static const char *DisconnectReasonText(DisconnectReason reason); // text-description of disconnect reason to aid in logging
// sets the handler object for this connection. If a handler object is specified, then the callback functions specified
// in UdpManager::Params are ignored for this connection and the handler is used for the callback instead.
// by default there is no handler.
void SetHandler(UdpConnectionHandler *handler);
UdpConnectionHandler *GetHandler() const;
// set and get the pass-through data value. Typically the application will set the pass through data
// in the callback function for establishing a connection, then it will use the pass through data
// in the callback function for routing packets.
void SetPassThroughData(void *passThroughData);
void *GetPassThroughData() const;
// when called this connection is marked as terminated. It is the responsibility of the application
// to explicitly destroy connections that are no longer connected. When this object is disconnected
// it calls the UdpManager and has itself removed from the list of active connections, at which point
// the only person having a pointer to this object is the application itself (which owns it)
// (if the UdpManager is deleted before all UdpConnections are destroyed, the UdpManager loops through
// all of the connections it has calling Disconnect on them such that they know that they no longer
// have a udp manager that they can send data through)
//
// setting a flushTimeout tells the connection to stay alive for that amount of time trying to send any pending
// reliable data before shutting down. Once the application calls Disconnect even with a flushTimeout, the application
// should not attempt to use the connection in any significant way (see docs and release notes for details)
// note: the notifyApplication parameter was removed from this function and the functionality of the library
// was changed such that ANYTIME the connection objects state changes to cStatusDisconnected, the OnTerminated callback
// function gets called.
void Disconnect(int flushTimeout = 0);
// sends a logical packet on the specified channel, returns FALSE if packet could not be queued for sending (should never happen)
// Internally, a packet that starts with a 0 byte is considered an internal control packet. If a logical packet starts with a 0
// byte, then there will an extra control byte of overhead in order to facilitate it. It is recommended that if packet size
// is critical, that you don't start the packet with a 0 byte. Typically an application will have a packet-type byte on the front
// of application packets; the application packet types should simply start at 1.
bool Send(UdpChannel channel, const void *data, int dataLen);
// same as the regular Send only it takes a LogicalPacket instead. There are two huge advantages to having it take a
// LogicalPacket. First, we can send the same LogicalPacket to multiple locations and each connection will not necessarily
// have to make its own copy of the data at the time it is put into the send queue (instead each connection just increments
// the buffer ref-count). Second, it allows the application to pre-generate very large packets (like file update packets potentially)
// and hold onto them for the entire length of the application, then, whenever any player needs that chunk of data, it can send them
// the already formatted LogicalPacket.
bool Send(UdpChannel channel, const LogicalPacket *packet);
// manually forces all channels to send-off any data they have queued up waiting for processing time to send
// this mainly applies to reliable channels. When you send a reliable packet, it actually only adds it to the reliable
// queue until the connection is given processing time by the manager object. This call forces it to attempt to
// send that queued data immediately (subject to normal flow control restrictions). This also flushes the multi-buffer
// for the channel. If you send reliable data and want to ensure that it goes out immediately after the send, this is the
// best call to make.
void FlushChannels();
// manually forces buffered data to be sent immediately
void FlushMultiBuffer();
// returns the number of bytes sent/received in the last second to this connection (accurate to within cBinResolution(25) milliseconds)
// these functions are not const as they expire the older bin data internally in order to calculate the number
int OutgoingBytesLastSecond();
int IncomingBytesLastSecond();
// returns the total number of bytes outstanding in all reliable channels. When this is zero, you know for sure
// that all sent reliable data has arrived at destination and is confirmed.
int TotalPendingBytes() const;
// returns how long has elapsed since this connection received data (in milliseconds)
int LastReceive() const;
// returns how long has elapsed since this connection received data (in milliseconds), using useStamp as the current time (optimization)
int LastReceive(UdpClockStamp useStamp) const;
// returns how long has elapsed since this connection sent data (in milliseconds)
int LastSend() const;
// returns how long this connection has been in existence (in milliseconds)
int ConnectionAge() const;
// returns the UdpManager object that is managing this connection
// will return nullptr if the connection has been disconnected for some reason (because disconnecting severes the link to UdpManager)
UdpManager *GetUdpManager() const;
// returns the 32-bit encryption-code that was negotiated as part of the connection-establishment process.
// this is a randomly generated number that both the client and the server have in common. It is exposed
// via this interface primarily to allow user-supplied encrypt routines access to it.
// this code is generated by the server side in response to a connect request.
int GetEncryptCode() const;
// this returns the connection-code. This is very similar to the encrypt-code in that it is randomly
// generated and both ends of the connection will report the same value. The difference is that this
// code's purpose is part of the internal protocol to ensure that old connections don't try to process
// new connection request packets. Unlike the encrypt-code, this value is generated by the client
// and is part of the connect-request packet. Nevertheless, since this number will be the same random
// number on both ends of the connection, it too can be used as a potential encryption key for the user
// supplied encrypt routines. It's not quite as secure as the encrypt code since this value in theory
// could be hacked to be something predictable on the client side.
int GetConnectCode() const;
// returns a sync-stamp that can be compared to other ServerSyncStamp's generated on other machines
// in order to calculate the one-way travel time for a packet. It can only accurate calculate
// packet travel times under 32 seconds, would should be completely safe. You must use the
// UdpManager::SyncStampDeltaTime function in order to calculate the elapsed time between
// the two stamps.
udp_ushort ServerSyncStampShort() const;
udp_uint ServerSyncStampLong() const;
int ServerSyncStampShortElapsed(udp_ushort syncStamp) const;
int ServerSyncStampLongElapsed(udp_uint syncStamp) const;
// returns the IP address/port this connection is linked to
UdpPlatformAddress GetDestinationIp() const;
int GetDestinationPort() const;
char *GetDestinationString(char *buf, int bufLen) const;
// statistical functions
void GetStats(UdpConnectionStatistics *cs);
void PingStatReset(); // resets the ping-stat information, causing it to resync the clock etc (if in clock-sync mode). Generally this is not done, it was added for backward compatibility
// functions for manipulating the automatic no-data-disconnect stuff on a per-connection basis
void SetNoDataTimeout(int noDataTimeout); // 0=never timeout, otherwise in milliseconds (overrides UdpManager::Params::noDataTimeout setting, which is the default)
int GetNoDataTimeout() const;
// functions for manipulating the keep-alive packet sending on a per-connection basis
void SetKeepAliveDelay(int keepAliveDelay);
int GetKeepAliveDelay() const;
// configures whether this connection is in silent-disconnect mode or not. By default, the connection is not in silent
// disconnect mode, which means that when this connection is terminated, it will send a final terminate-packet to the
// other side telling them that we are disconnected, allowing them to quickly realize that the connection is now dead.
// In some circumstances, it may be desireable to not do this, and this can be accomplished by calling this function
// passing in 'true' to put it in silent mode. This may be desireable in cases where you are disconnecting a cheater
// and don't want them to have immediate notification that they did something bad. Or, if you are attempting to test
// timeout functionality on the other end and want to simulate a truly dead connection. Normally, you will not want
// to mess with this. It was added to the API to support some internal functionality, see its use in the source-code
// or release-notes for details.
void SetSilentDisconnect(bool silent);
// returns the current queue-status of the reliable channel specified. Unreliable channels will always report zero.
struct ChannelStatus
{
int totalPendingBytes; // total bytes of data in channel that have yet to be acknowledged (includes queuedBytes plus physical-packet bytes that have yet to be acknowledged)
int queuedPackets; // number of logical packets in the queue
int queuedBytes; // number of bytes in the logical queue (the logical queue does NOT include pending physical packets)
int incomingLargeTotal; // total number of bytes in the currently incoming logical packet (only meaningful obviously if a fragmented file is in tranist)
int incomingLargeSoFar; // number of bytes received so far in the currently incoming logical packet
int oldestUnacknowledgedAge; // age of the oldest unacknowledged (but sent) packet (in milliseconds)
int duplicatePacketsReceived; // number of times we received a packet that we had already received
int resentPacketsAccelerated; // number of times we have resent a packet due to receiving a later packet in the series
int resentPacketsTimedOut; // number of times we have resent a packet due to the ack-timeout expiring
int congestionSlowStartThreshhold; // current threshhold for slow-start algorithm
int congestionWindowSize; // current sliding window size
int ackAveragePing; // average time for a packet to be acknowledged (used in calculating optimal resend timeouts)
};
void GetChannelStatus(UdpChannel channel, ChannelStatus *channelStatus) const;
protected:
friend class UdpManager;
friend class UdpReliableChannel;
// note: if connectPacket is nullptr, that means this connection object is being created to establish
// a new connection to the specified ip/port (ie. the connection starts out in cStatusNegotiating mode)
// if connectPacket is non-nullptr, that menas this connection object is being created to handle an
// incoming connect request and it will start out in cStatusConnected mode.
UdpConnection(UdpManager *udpManager, UdpPlatformAddress destIp, int destPort, int timeout); // starts connection-establishment protocol
UdpConnection(UdpManager *udpManager, const UdpManager::PacketHistoryEntry *e); // starts already connected, replying to connection request
// gives this connection processing time (only given processing time by the manager object and then
// only when the connection has scheduled itself to receive processing time)
void GiveTime(bool fromManager);
void ProcessRawPacket(const UdpManager::PacketHistoryEntry *e);
void PortUnreachable();
void FlagPortUnreachable();
// these functions are called by the manager to forward these events to this connection
// all events get sent to the UdpManager for potential event-queuing, then forwarded back
// to the connection for actual deliver, since the connection object needs to hold a
// guard such that the handler doesn't get deleted during event delivery
void OnRoutePacket(const udp_uchar *data, int dataLen);
void OnConnectComplete();
void OnTerminated();
void OnCrcReject(const udp_uchar *data, int dataLen);
void OnPacketCorrupt(const udp_uchar *data, int dataLen, UdpCorruptionReason reason);
protected:
typedef int (UdpConnection::* IEncryptFunction)(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
typedef int (UdpConnection::* IDecryptFunction)(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
IDecryptFunction mDecryptFunction[cEncryptPasses];
IEncryptFunction mEncryptFunction[cEncryptPasses];
UdpPlatformAddress mIp;
int mPort;
int mSimulateOutgoingQueueBytes; // used by UdpManager to track how many bytes are in it's simulation queue headed to each destination
private:
~UdpConnection();
void Init(UdpManager *udpManager, UdpPlatformAddress destIp, int destPort);
// note: BufferedSend is capable of optionally taking two chunks of data at once, which are then concatenated together as if they were one chunk of data
// into the multi-buffer. Providing this facility prevents the UdpReliableChannel object from having to make a copy of all the data it sends
// in order to stick a realiable header on it.
// we don't bother extending this down to the PhysicalSend (in case the BufferedSend does a pass through due to size) because the encryption code
// is incapable of sourcing from two different chunks and outputting to one chunk. It's not possible to change that either, since the encyption
// takes place 32 bits at a time and you could end up straddling boundaries between chunks.
void RawSend(const udp_uchar *data, int dataLen); // nothing happens to the data here, it is given to the udpmanager and sent out the port
void PhysicalSend(const udp_uchar *data, int dataLen, bool appendAllowed); // sends a physical packet (encrypts and adds crc bytes)
udp_uchar *BufferedSend(const udp_uchar *data, int dataLen, const udp_uchar *data2, int dataLen2, bool appendAllowed); // buffers logical packets waiting til we have more data (makes multi-packets)
bool InternalSend(UdpChannel channel, const udp_uchar *data, int dataLen, const udp_uchar *data2 = nullptr, int dataLen2 = 0);
void InternalGiveTime();
void InternalDisconnect(int flushTimeout, DisconnectReason reason);
void ProcessCookedPacket(const udp_uchar *data, int dataLen);
void DecryptIt(const udp_uchar *data, int dataLen);
void ScheduleTimeNow();
void ExpireSendBin();
void ExpireReceiveBin();
void SendTerminatePacket(int connectCode, DisconnectReason reason);
void CallbackRoutePacket(const udp_uchar *data, int dataLen);
void CallbackCorruptPacket(const udp_uchar *data, int dataLen, UdpCorruptionReason reason);
bool IsNonEncryptPacket(const udp_uchar *data) const;
// these encrypt-method functions return the length of the encrypted/decrypted data
// new methods of encryption/compression can be easily added by simply creating the
// functions for them and changing the SetupEncryptModel function as appropriate
// since raw packets are encrypted in the first place and have a limited size
// the decrypted data will never be larger than a maxRawPacketSize. Both of encrypt
// and decrypt are guaranteed to have enough room in dest buffers to hold the results.
// Encryption function is allowed to expand the data at most the number of bytes
// it reserves for this purpose in the SetupEncryptModel function.
int EncryptNone(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int DecryptNone(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int EncryptXor(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int DecryptXor(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int EncryptXorBuffer(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int DecryptXorBuffer(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int EncryptUserSupplied(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int DecryptUserSupplied(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int EncryptUserSupplied2(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
int DecryptUserSupplied2(udp_uchar *destData, const udp_uchar *sourceData, int sourceLen);
void SetupEncryptModel();
UdpLinkedListMember<UdpConnection> mConnectionLink;
UdpLinkedListMember<UdpConnection> mDisconnectPendingLink;
Status mStatus;
void *mPassThroughData;
UdpManager *mUdpManager;
int mConnectCode;
UdpConnectionStatistics mConnectionStats;
UdpClockStamp mConnectionCreateTime;
int mConnectAttemptTimeout;
int mNoDataTimeout;
DisconnectReason mDisconnectReason;
DisconnectReason mOtherSideDisconnectReason;
bool mFlaggedPortUnreachable;
bool mSilentDisconnect;
UdpReliableChannel *mChannel[cReliableChannelCount];
struct Configuration
{
int encryptCode;
int crcBytes;
EncryptMethod encryptMethod[cEncryptPasses];
int maxRawPacketSize; // negotiated maxRawPacketSize (ie. smaller of what two sides are set to)
};
Configuration mConnectionConfig;
int mOtherSideProtocolVersion;
UdpClockStamp mLastClockSyncTime;
UdpClockStamp mDataHoldTime;
UdpClockStamp mLastSendTime;
UdpClockStamp mLastReceiveTime;
UdpClockStamp mLastPortAliveTime;
udp_uchar *mMultiBufferData;
udp_uchar *mMultiBufferPtr;
int mOrderedCountOutgoing;
int mOrderedCountOutgoing2;
udp_ushort mOrderedStampLast;
udp_ushort mOrderedStampLast2;
udp_uchar *mEncryptXorBuffer;
int mEncryptExpansionBytes;
udp_uint mSyncTimeDelta;
int mSyncStatTotal;
int mSyncStatCount;
int mSyncStatLow;
int mSyncStatHigh;
int mSyncStatLast;
int mSyncStatMasterRoundTime;
UdpClockStamp mSyncStatMasterFixupTime;
bool mGettingTime;
UdpConnectionHandler *mHandler;
int mKeepAliveDelay;
UdpClockStamp mIcmpErrorRetryStartStamp;
UdpClockStamp mPortRemapRequestStartStamp;
UdpClockStamp mDisconnectFlushStamp;
int mDisconnectFlushTimeout;
mutable UdpPlatformGuardObject mGuard;
mutable UdpPlatformGuardObject mHandlerGuard;
// data rate management functions
enum { cBinResolution = 25, cBinCount = 1000 / cBinResolution };
udp_int64 mLastSendBin;
udp_int64 mLastReceiveBin;
int mOutgoingBytesLastSecond;
int mIncomingBytesLastSecond;
int mSendBin[cBinCount];
int mReceiveBin[cBinCount];
//////////////////////////////////////////////////////////////////////////////////////////////////////
// The following structs represent what the internal packets look like. In practice, most of these
// structs are never used and exist only for documentation clarity. Internally packets are
// manually assembled such that struct packing and byte-ordering issues won't be an issue.
//////////////////////////////////////////////////////////////////////////////////////////////////////
struct UdpPacketConnect
{
udp_uchar zeroByte;
udp_uchar packetType;
int protocolVersion;
int connectCode;
int maxRawPacketSize;
};
struct UdpPacketConfirm
{
udp_uchar zeroByte;
udp_uchar packetType;
int connectCode;
Configuration config;
int maxRawPacketSize;
};
struct UdpPacketTerminate
{
udp_uchar zeroByte;
udp_uchar packetType;
int connectCode;
};
struct UdpPacketKeepAlive
{
udp_uchar zeroByte;
udp_uchar packetType;
};
struct UdpPacketGroup
{
// this format is prepped by the GroupLogicalPacket object, which reports itself to the UdpConnection object as an internal packet
// type such that it doesn't get treated as an application-packet even though the application is the one sending it
udp_uchar zeroByte;
udp_uchar packetType;
// variableValue/data, repeated...
};
struct UdpPacketClockSync
{
udp_uchar zeroByte;
udp_uchar packetType;
udp_ushort timeStamp;
int masterPingTime;
int averagePingTime;
int lowPingTime;
int highPingTime;
int lastPingTime;
udp_int64 ourSent;
udp_int64 ourReceived;
};
struct UdpPacketClockReflect
{
udp_uchar zeroByte;
udp_uchar packetType;
udp_ushort timeStamp;
udp_uint serverSyncStampLong;
udp_int64 yourSent;
udp_int64 yourReceived;
udp_int64 ourSent;
udp_int64 ourReceived;
};
struct UdpPacketReliable
{
udp_uchar zeroByte;
udp_uchar packetType;
udp_ushort reliableStamp;
};
struct UdpPacketReliableFragmentStart
{
UdpPacketReliable reliable;
int length;
};
struct UdpPacketAck
{
udp_uchar zeroByte;
udp_uchar packetType;
udp_ushort reliableStamp;
};
struct UdpPacketOrdered
{
udp_uchar zeroByte;
udp_uchar packetType;
udp_ushort orderStamp;
};
enum { cUdpPacketReliableSize = 4 };
enum { cUdpPacketOrderedSize = 4 };
protected:
friend class GroupLogicalPacket; // so it can see cUdpPacketGroup enum
// note: cUdpPacketReliable, cUdpPacketFragment both indicate a reliable-packet header. They are marked
// differently such that we can support large packets without any additional header overhead, a fragment marked packet means
// that the packet is part of a larger packet being assembled. The first fragment has an additional 4 bytes on the header specifying
// the length to follow. The order of those entries is important
enum UdpPacketType { cUdpPacketZeroEscape, cUdpPacketConnect, cUdpPacketConfirm, cUdpPacketMulti, cUdpPacketBig
, cUdpPacketTerminate, cUdpPacketKeepAlive
, cUdpPacketClockSync, cUdpPacketClockReflect
, cUdpPacketReliable1, cUdpPacketReliable2, cUdpPacketReliable3, cUdpPacketReliable4
, cUdpPacketFragment1, cUdpPacketFragment2, cUdpPacketFragment3, cUdpPacketFragment4
, cUdpPacketAck1, cUdpPacketAck2, cUdpPacketAck3, cUdpPacketAck4
, cUdpPacketAckAll1, cUdpPacketAckAll2, cUdpPacketAckAll3, cUdpPacketAckAll4
, cUdpPacketGroup, cUdpPacketOrdered, cUdpPacketOrdered2, cUdpPacketPortAlive
, cUdpPacketUnreachableConnection, cUdpPacketRequestRemap };
};
/////////////////////////////////////////////////////////////////////////
// inline implementations
/////////////////////////////////////////////////////////////////////////
// UdpConnection
inline void UdpConnection::ScheduleTimeNow()
{
// if we are current in our GiveTime function getting time, then there is no need to reprioritize to 0 when we send a raw packet, since
// the last thing we do in out GiveTime is do a scheduling calculation based on the last time a packet was sent. This little check
// prevents us from reprioritizing to 0, only to shortly thereafter be reprioritized to where we actually belong.
if (!mGettingTime)
{
if (mUdpManager != nullptr)
mUdpManager->SetPriority(this, 0);
}
}
inline void UdpConnection::SetHandler(UdpConnectionHandler *handler)
{
UdpGuard guard(&mHandlerGuard);
mHandler = handler;
}
inline UdpConnectionHandler *UdpConnection::GetHandler() const
{
UdpGuard guard(&mHandlerGuard);
return(mHandler);
}
inline bool UdpConnection::IsNonEncryptPacket(const udp_uchar *data) const
{
if (data[0] == 0)
{
if (data[1] == cUdpPacketConnect || data[1] == cUdpPacketConfirm || data[1] == cUdpPacketUnreachableConnection || data[1] == cUdpPacketRequestRemap)
return(true);
}
return(false);
}
inline int UdpConnection::GetEncryptCode() const
{
UdpGuard guard(&mGuard);
return(mConnectionConfig.encryptCode);
}
inline int UdpConnection::GetConnectCode() const
{
UdpGuard guard(&mGuard);
return(mConnectCode);
}
inline int UdpConnection::LastReceive(UdpClockStamp useStamp) const
{
UdpGuard guard(&mGuard);
return(UdpMisc::ClockDiff(mLastReceiveTime, useStamp));
}
inline int UdpConnection::LastReceive() const
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
return(mUdpManager->CachedClockElapsed(mLastReceiveTime));
}
inline int UdpConnection::ConnectionAge() const
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
return(mUdpManager->CachedClockElapsed(mConnectionCreateTime));
}
inline int UdpConnection::LastSend() const
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
return(mUdpManager->CachedClockElapsed(mLastSendTime));
}
inline udp_ushort UdpConnection::ServerSyncStampShort() const
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
return((udp_ushort)(mUdpManager->LocalSyncStampShort() + (mSyncTimeDelta & 0xffff)));
}
inline udp_uint UdpConnection::ServerSyncStampLong() const
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
return(mUdpManager->LocalSyncStampLong() + mSyncTimeDelta);
}
inline int UdpConnection::ServerSyncStampShortElapsed(udp_ushort syncStamp) const
{
return(UdpMisc::SyncStampShortDeltaTime(syncStamp, ServerSyncStampShort()));
}
inline int UdpConnection::ServerSyncStampLongElapsed(udp_uint syncStamp) const
{
return(UdpMisc::SyncStampLongDeltaTime(syncStamp, ServerSyncStampLong()));
}
inline UdpManager *UdpConnection::GetUdpManager() const
{
UdpGuard guard(&mGuard);
return(mUdpManager);
}
inline UdpConnection::Status UdpConnection::GetStatus() const
{
UdpGuard guard(&mGuard);
return(mStatus);
}
inline UdpConnection::DisconnectReason UdpConnection::GetDisconnectReason() const
{
UdpGuard guard(&mGuard);
return(mDisconnectReason);
}
inline UdpConnection::DisconnectReason UdpConnection::GetOtherSideDisconnectReason() const
{
UdpGuard guard(&mGuard);
return(mOtherSideDisconnectReason);
}
inline int UdpConnection::OutgoingBytesLastSecond()
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
ExpireSendBin();
return(mOutgoingBytesLastSecond);
}
inline int UdpConnection::IncomingBytesLastSecond()
{
UdpGuard guard(&mGuard);
if (mUdpManager == nullptr)
return(0);
ExpireReceiveBin();
return(mIncomingBytesLastSecond);
}
inline void UdpConnection::SetPassThroughData(void *passThroughData)
{
UdpGuard guard(&mGuard);
mPassThroughData = passThroughData;
}
inline void *UdpConnection::GetPassThroughData() const
{
UdpGuard guard(&mGuard);
return(mPassThroughData);
}
inline UdpPlatformAddress UdpConnection::GetDestinationIp() const
{
UdpGuard guard(&mGuard);
return(mIp);
}
inline int UdpConnection::GetDestinationPort() const
{
UdpGuard guard(&mGuard);
return(mPort);
}
inline void UdpConnection::SetNoDataTimeout(int noDataTimeout)
{
UdpGuard guard(&mGuard);
mNoDataTimeout = noDataTimeout;
}
inline int UdpConnection::GetNoDataTimeout() const
{
UdpGuard guard(&mGuard);
return(mNoDataTimeout);
}
inline void UdpConnection::Disconnect(int flushTimeout)
{
UdpRef ref(this); // in case application releases us during the disconnect, we need to hold this reference so our guard object can be destroyed first
UdpGuard guard(&mGuard);
InternalDisconnect(flushTimeout, cDisconnectReasonApplication);
}
inline void UdpConnection::SetKeepAliveDelay(int keepAliveDelay)
{
UdpGuard guard(&mGuard);
mKeepAliveDelay = keepAliveDelay;
}
inline int UdpConnection::GetKeepAliveDelay() const
{
UdpGuard guard(&mGuard);
return(mKeepAliveDelay);
}
} // namespace
#endif