📄 netconnection.h
字号:
/// resolveGhost() is used on the client side, and resolveObjectFromGhostIndex() on the server side, to
/// turn ghost IDs into object references.
///
/// The NetConnection is a SimGroup. On the client side, it contains all the objects which have been
/// ghosted to that client. On the server side, it is empty; it can be used (typically in script) to
/// hold objects related to the connection. For instance, you might place an observation camera in the
/// NetConnnection. In both cases, when the connection is destroyed, so are the contained objects.
///
/// @see NetObject, which is the superclass for ghostable objects, and ShapeBase, which is the base
/// for player and vehicle classes.
///
/// @nosubgrouping
class NetConnection : public ConnectionProtocol, public SimGroup
{
friend class NetInterface;
#ifdef TGE_RPG
friend class NetworkBase;
friend class NetUDP;
friend class NetManager;
friend class NetTCP;
#endif
typedef SimGroup Parent;
public:
/// Structure to track ghost references in packets.
///
/// Every packet we send out with an update from a ghost causes one of these to be
/// allocated. mask is used to track what states were sent; that way if a packet is
/// dropped, we can easily manipulate the stored states and figure out what if any data
/// we need to resend.
///
struct GhostRef
{
U32 mask; ///< States we transmitted.
U32 ghostInfoFlags; ///< Flags from GhostInfo::Flags
GhostInfo *ghost; ///< Reference to the GhostInfo we're from.
GhostRef *nextRef; ///< Next GhostRef in this packet.
GhostRef *nextUpdateChain; ///< Next update we sent for this ghost.
};
enum Constants
{
HashTableSize = 127,
};
void sendDisconnectPacket(const char *reason);
virtual bool canRemoteCreate();
virtual void onTimedOut();
virtual void onConnectTimedOut();
virtual void onDisconnect(const char *reason);
virtual void onConnectionRejected(const char *reason);
virtual void onConnectionEstablished(bool isInitiator);
virtual void handleStartupError(const char *errorString);
virtual void writeConnectRequest(BitStream *stream);
virtual bool readConnectRequest(BitStream *stream, const char **errorString);
virtual void writeConnectAccept(BitStream *stream);
virtual bool readConnectAccept(BitStream *stream, const char **errorString);
void connect(const NetAddress *address);
//----------------------------------------------------------------
/// @name Global Connection List
/// @{
private:
///
NetConnection *mNextConnection; ///< Next item in list.
NetConnection *mPrevConnection; ///< Previous item in list.
static NetConnection *mConnectionList; ///< Head of list.
public:
static NetConnection *getConnectionList() { return mConnectionList; }
NetConnection *getNext() { return mNextConnection; }
/// @}
//----------------------------------------------------------------
enum NetConnectionFlags
{
ConnectionToServer = BIT(0),
ConnectionToClient = BIT(1),
LocalClientConnection = BIT(2),
NetworkConnection = BIT(3),
};
private:
BitSet32 mTypeFlags;
U32 mNetClassGroup; ///< The NetClassGroup of this connection.
/// @name Statistics
/// @{
U32 mLastUpdateTime;
F32 mRoundTripTime;
F32 mPacketLoss;
U32 mSimulatedPing;
F32 mSimulatedPacketLoss;
/// @}
/// @name State
/// @{
U32 mProtocolVersion;
U32 mSendDelayCredit;
U32 mConnectSequence;
U32 mAddressDigest[4];
bool mEstablished;
bool mMissionPathsSent;
struct NetRate
{
U32 updateDelay;
S32 packetSize;
bool changed;
};
NetRate mCurRate;
NetRate mMaxRate;
/// If we're doing a "short circuited" connection, this stores
/// a pointer to the other side.
SimObjectPtr<NetConnection> mRemoteConnection;
NetAddress mNetAddress;
/// @}
/// @name Timeout Management
/// @{
U32 mPingSendCount;
U32 mPingRetryCount;
U32 mLastPingSendTime;
/// @}
/// @name Connection Table
///
/// We store our connections on a hash table so we can
/// quickly find them.
/// @{
NetConnection *mNextTableHash;
static NetConnection *mHashTable[HashTableSize];
/// @}
protected:
static SimObjectPtr<NetConnection> mServerConnection;
static SimObjectPtr<NetConnection> mLocalClientConnection;
static bool mFilesWereDownloaded;
#ifdef TGE_RPG
public:
#endif
U32 mConnectSendCount;
U32 mConnectLastSendTime;
public:
static NetConnection *getConnectionToServer() { return mServerConnection; }
static NetConnection *getLocalClientConnection() { return mLocalClientConnection; }
static void setLocalClientConnection(NetConnection *conn) { mLocalClientConnection = conn; }
U32 getNetClassGroup() { return mNetClassGroup; }
static bool filesWereDownloaded() { return mFilesWereDownloaded; }
static char *getErrorBuffer() { return mErrorBuffer; }
#ifdef TORQUE_DEBUG_NET
bool mLogging;
void setLogging(bool logging) { mLogging = logging; }
#endif
void setSimulatedNetParams(F32 packetLoss, U32 ping)
{ mSimulatedPacketLoss = packetLoss; mSimulatedPing = ping; }
bool isConnectionToServer() { return mTypeFlags.test(ConnectionToServer); }
bool isLocalConnection() { return !mRemoteConnection.isNull() ; }
bool isNetworkConnection() { return mTypeFlags.test(NetworkConnection); }
void setIsConnectionToServer() { mTypeFlags.set(ConnectionToServer); }
void setIsLocalClientConnection() { mTypeFlags.set(LocalClientConnection); }
void setNetworkConnection(bool net) { mTypeFlags.set(BitSet32(NetworkConnection), net); }
virtual void setEstablished();
/// Call this if the "connection" is local to this app. This short-circuits the protocol layer.
void setRemoteConnectionObject(NetConnection *connection) { mRemoteConnection = connection; };
void setSequence(U32 connectSequence);
void setAddressDigest(U32 digest[4]);
void getAddressDigest(U32 digest[4]);
U32 getSequence();
void setProtocolVersion(U32 protocolVersion) { mProtocolVersion = protocolVersion; }
U32 getProtocolVersion() { return mProtocolVersion; }
F32 getRoundTripTime() { return mRoundTripTime; }
F32 getPacketLoss() { return( mPacketLoss ); }
static char mErrorBuffer[256];
static void setLastError(const char *fmt,...);
void checkMaxRate();
void handlePacket(BitStream *stream);
void processRawPacket(BitStream *stream);
void handleNotify(bool recvd);
void handleConnectionEstablished();
void keepAlive();
const NetAddress *getNetAddress();
void setNetAddress(const NetAddress *address);
Net::Error sendPacket(BitStream *stream);
private:
void netAddressTableInsert();
void netAddressTableRemove();
public:
/// Find a NetConnection, if any, with the specified address.
static NetConnection *lookup(const NetAddress *remoteAddress);
bool checkTimeout(U32 time); ///< returns true if the connection timed out
void checkPacketSend(bool force);
bool missionPathsSent() const { return mMissionPathsSent; }
void setMissionPathsSent(const bool s) { mMissionPathsSent = s; }
static void consoleInit();
void onRemove();
NetConnection();
~NetConnection();
public:
enum NetConnectionState
{
NotConnected,
AwaitingChallengeResponse, ///< We've sent a challenge request, awaiting the response.
AwaitingConnectRequest, ///< We've received a challenge request and sent a challenge response.
AwaitingConnectResponse, ///< We've received a challenge response and sent a connect request.
Connected, ///< We've accepted a connect request, or we've received a connect response accept.
};
U32 mConnectionSendCount; ///< number of connection messages we've sent.
U32 mConnectionState; ///< State of the connection, from NetConnectionState.
void setConnectionState(U32 state) { mConnectionState = state; }
U32 getConnectionState() { return mConnectionState; }
void setGhostFrom(bool ghostFrom); ///< Sets whether ghosts transmit from this side of the connection.
void setGhostTo(bool ghostTo); ///< Sets whether ghosts are allowed from the other side of the connection.
void setSendingEvents(bool sending); ///< Sets whether this side actually sends the events that are posted to it.
void setTranslatesStrings(bool xl); ///< Sets whether this connection is capable of translating strings.
void setNetClassGroup(U32 group); ///< Sets the group of NetClasses this connection traffics in.
bool isEstablished() { return mEstablished; } ///< Is the connection established?
DECLARE_CONOBJECT(NetConnection);
/// Structure to track packets and what we sent over them.
///
/// We need to know what is sent in each packet, so that if a packet is
/// dropped, we know what to resend. This is the structure we use to track
/// this data.
struct PacketNotify
{
bool rateChanged; ///< Did the rate change on this packet?
bool maxRateChanged; ///< Did the max rate change on this packet?
U32 sendTime; ///< Timestampe, when we sent this packet.
NetEventNote *eventList; ///< Linked list of events sent over this packet.
GhostRef *ghostList; ///< Linked list of ghost updates we sent in this packet.
SubPacketRef *subList; ///< Defined by subclass - used as desired.
PacketNotify *nextPacket; ///< Next packet sent.
PacketNotify();
};
virtual PacketNotify *allocNotify();
PacketNotify *mNotifyQueueHead; ///< Head of packet notify list.
PacketNotify *mNotifyQueueTail; ///< Tail of packet notify list.
protected:
virtual void readPacket(BitStream *bstream);
virtual void writePacket(BitStream *bstream, PacketNotify *note);
virtual void packetReceived(PacketNotify *note);
virtual void packetDropped(PacketNotify *note);
virtual void connectionError(const char *errorString);
//----------------------------------------------------------------
/// @name Event Manager
/// @{
private:
NetEventNote *mSendEventQueueHead;
NetEventNote *mSendEventQueueTail;
NetEventNote *mUnorderedSendEventQueueHead;
NetEventNote *mUnorderedSendEventQueueTail;
NetEventNote *mWaitSeqEvents;
NetEventNote *mNotifyEventList;
static FreeListChunker<NetEventNote> mEventNoteChunker;
bool mSendingEvents;
S32 mNextSendEventSeq;
S32 mNextRecvEventSeq;
S32 mLastAckedEventSeq;
enum NetEventConstants {
InvalidSendEventSeq = -1,
FirstValidSendEventSeq = 0
};
void eventOnRemove();
void eventPacketDropped(PacketNotify *notify);
void eventPacketReceived(PacketNotify *notify);
void eventWritePacket(BitStream *bstream, PacketNotify *notify);
void eventReadPacket(BitStream *bstream);
void eventWriteStartBlock(ResizeBitStream *stream);
void eventReadStartBlock(BitStream *stream);
public:
/// Post an event to this connection.
bool postNetEvent(NetEvent *event);
/// @}
//----------------------------------------------------------------
/// @name Networked string table
/// @{
private:
bool mTranslateStrings;
ConnectionStringTable *mStringTable;
public:
void mapString(U32 netId, StringHandle &string)
{ mStringTable->mapString(netId, string); }
U32 checkString(StringHandle &string, bool *isOnOtherSide = NULL)
{ if(mStringTable) return mStringTable->checkString(string, isOnOtherSide); else return 0; }
U32 getNetSendId(StringHandle &string)
{ if(mStringTable) return mStringTable->getNetSendId(string); else return 0;}
void confirmStringReceived(StringHandle &string, U32 index)
{ if(!isRemoved()) mStringTable->confirmStringReceived(string, index); }
StringHandle translateRemoteStringId(U32 id) { return mStringTable->lookupString(id); }
void validateSendString(const char *str);
void packString(BitStream *stream, const char *str);
void unpackString(BitStream *stream, char readBuffer[1024]);
void packStringHandleU(BitStream *stream, StringHandle &h);
StringHandle unpackStringHandleU(BitStream *stream);
/// @}
//----------------------------------------------------------------
/// @name Ghost manager
/// @{
protected:
enum GhostStates
{
GhostAlwaysDone,
ReadyForNormalGhosts,
EndGhosting,
GhostAlwaysStarting,
SendNextDownloadRequest,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -