mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
* [Logging] Unify netcode logging * More tweaks, generator * Exclude OP_SpecialMesg at callback level * Consolidate packet loggers * Log at EQStream level instead of proxy * Fix C->S * Server to server logging * C-S for Loginserver * Hook UCS for C->S * Update eqemu_logsys.h * World C->S logging * Translate opcodes through patch system for client to server * Additional logging requests * Add detailed opcode translation logging * vStringFormat resiliency * Translate loginserver C->S * Simplify out message string (reduce copies) and ignore legacy formats * Update eqemu_logsys.cpp * Log file format * Handle deprecated categories
320 lines
8.5 KiB
C++
320 lines
8.5 KiB
C++
#ifndef _EQSTREAM_H
|
|
#define _EQSTREAM_H
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include <queue>
|
|
#include <deque>
|
|
|
|
#ifndef WIN32
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
#include "../common/misc.h"
|
|
#include "../common/opcodemgr.h"
|
|
#include "../common/timer.h"
|
|
|
|
#include "eq_packet.h"
|
|
#include "eq_stream_intf.h"
|
|
#include "eq_stream_type.h"
|
|
#include "mutex.h"
|
|
|
|
class EQApplicationPacket;
|
|
class EQProtocolPacket;
|
|
|
|
#define FLAG_COMPRESSED 0x01
|
|
#define FLAG_ENCODED 0x04
|
|
|
|
#ifndef RATEBASE
|
|
#define RATEBASE 1048576
|
|
#endif
|
|
|
|
#ifndef DECAYBASE
|
|
#define DECAYBASE 78642
|
|
#endif
|
|
|
|
#ifndef RETRANSMIT_TIMEOUT_MULT
|
|
#define RETRANSMIT_TIMEOUT_MULT 3.0
|
|
#endif
|
|
|
|
#ifndef RETRANSMIT_TIMEOUT_MAX
|
|
#define RETRANSMIT_TIMEOUT_MAX 5000
|
|
#endif
|
|
|
|
#ifndef AVERAGE_DELTA_MAX
|
|
#define AVERAGE_DELTA_MAX 2500
|
|
#endif
|
|
|
|
#ifndef RETRANSMIT_ACKED_PACKETS
|
|
#define RETRANSMIT_ACKED_PACKETS true
|
|
#endif
|
|
|
|
#ifndef MAX_SESSION_RETRIES
|
|
#define MAX_SESSION_RETRIES 30
|
|
#endif
|
|
|
|
#pragma pack(1)
|
|
struct SessionRequest {
|
|
uint32 UnknownA;
|
|
uint32 Session;
|
|
uint32 MaxLength;
|
|
};
|
|
|
|
struct SessionResponse {
|
|
uint32 Session;
|
|
uint32 Key;
|
|
uint8 UnknownA;
|
|
uint8 Format;
|
|
uint8 UnknownB;
|
|
uint32 MaxLength;
|
|
uint32 UnknownD;
|
|
};
|
|
|
|
//Deltas are in ms, representing round trip times
|
|
struct ClientSessionStats {
|
|
/*000*/ uint16 RequestID;
|
|
/*002*/ uint32 last_local_delta;
|
|
/*006*/ uint32 average_delta;
|
|
/*010*/ uint32 low_delta;
|
|
/*014*/ uint32 high_delta;
|
|
/*018*/ uint32 last_remote_delta;
|
|
/*022*/ uint64 packets_sent;
|
|
/*030*/ uint64 packets_received;
|
|
/*038*/
|
|
};
|
|
|
|
struct ServerSessionStats {
|
|
/*000*/ uint16 RequestID;
|
|
/*002*/ uint32 ServerTime;
|
|
/*006*/ uint64 packets_sent_echo;
|
|
/*014*/ uint64 packets_received_echo;
|
|
/*022*/ uint64 packets_sent;
|
|
/*030*/ uint64 packets_received;
|
|
/*038*/
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
class OpcodeManager;
|
|
class EQRawApplicationPacket;
|
|
|
|
class EQStream : public EQStreamInterface {
|
|
friend class EQStreamPair; //for collector.
|
|
protected:
|
|
typedef enum {
|
|
SeqPast,
|
|
SeqInOrder,
|
|
SeqFuture
|
|
} SeqOrder;
|
|
|
|
uint32 remote_ip;
|
|
uint16 remote_port;
|
|
uint8 buffer[8192];
|
|
unsigned char *oversize_buffer;
|
|
uint32 oversize_offset,oversize_length;
|
|
uint8 app_opcode_size;
|
|
EQStreamType StreamType;
|
|
bool compressed,encoded;
|
|
uint32 retransmittimer;
|
|
uint32 retransmittimeout;
|
|
|
|
uint16 sessionAttempts;
|
|
bool streamactive;
|
|
|
|
//uint32 buffer_len;
|
|
|
|
uint32 Session, Key;
|
|
uint16 NextInSeq;
|
|
uint32 MaxLen;
|
|
uint16 MaxSends;
|
|
|
|
uint8 active_users; //how many things are actively using this
|
|
Mutex MInUse;
|
|
|
|
EQStreamState State;
|
|
Mutex MState;
|
|
|
|
uint32 LastPacket;
|
|
Mutex MVarlock;
|
|
|
|
// Ack sequence tracking.
|
|
long NextAckToSend;
|
|
long LastAckSent;
|
|
long GetNextAckToSend();
|
|
long GetLastAckSent();
|
|
void AckPackets(uint16 seq);
|
|
void SetNextAckToSend(uint32);
|
|
void SetLastAckSent(uint32);
|
|
|
|
Mutex MAcks;
|
|
|
|
// Packets waiting to be sent (all protected by MOutboundQueue)
|
|
std::queue<EQProtocolPacket *> NonSequencedQueue;
|
|
std::deque<EQProtocolPacket *> SequencedQueue;
|
|
uint16 NextOutSeq;
|
|
uint16 SequencedBase; //the sequence number of SequencedQueue[0]
|
|
Mutex MOutboundQueue;
|
|
|
|
//a buffer we use for compression/decompression
|
|
unsigned char _tempBuffer[2048];
|
|
|
|
// Packets waiting to be processed
|
|
std::vector<EQRawApplicationPacket *> InboundQueue;
|
|
std::map<unsigned short,EQProtocolPacket *> PacketQueue; //not mutex protected, only accessed by caller of Process()
|
|
Mutex MInboundQueue;
|
|
|
|
static uint16 MaxWindowSize;
|
|
|
|
int32 BytesWritten;
|
|
|
|
uint64 sent_packet_count;
|
|
uint64 received_packet_count;
|
|
|
|
Mutex MRate;
|
|
int32 RateThreshold;
|
|
int32 DecayRate;
|
|
uint32 AverageDelta;
|
|
|
|
OpcodeManager **OpMgr;
|
|
|
|
EQRawApplicationPacket *MakeApplicationPacket(EQProtocolPacket *p);
|
|
EQRawApplicationPacket *MakeApplicationPacket(const unsigned char *buf, uint32 len);
|
|
EQProtocolPacket *MakeProtocolPacket(const unsigned char *buf, uint32 len);
|
|
void SendPacket(uint16 opcode, EQApplicationPacket *p);
|
|
|
|
void SetState(EQStreamState state);
|
|
|
|
void SendSessionResponse();
|
|
void SendSessionRequest();
|
|
void SendAck(uint16 seq);
|
|
void SendOutOfOrderAck(uint16 seq);
|
|
void QueuePacket(EQProtocolPacket *p);
|
|
void SendPacket(EQProtocolPacket *p);
|
|
void NonSequencedPush(EQProtocolPacket *p);
|
|
void SequencedPush(EQProtocolPacket *p);
|
|
void WritePacket(int fd,EQProtocolPacket *p);
|
|
|
|
|
|
uint32 GetKey() { return Key; }
|
|
void SetKey(uint32 k) { Key=k; }
|
|
void SetSession(uint32 s) { Session=s; }
|
|
|
|
void ProcessPacket(EQProtocolPacket *p);
|
|
|
|
bool Stale(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); }
|
|
|
|
void InboundQueuePush(EQRawApplicationPacket *p);
|
|
EQRawApplicationPacket *PeekPacket(); //for collector.
|
|
EQRawApplicationPacket *PopRawPacket(); //for collector.
|
|
|
|
void InboundQueueClear();
|
|
void OutboundQueueClear();
|
|
void PacketQueueClear();
|
|
|
|
void ProcessQueue();
|
|
EQProtocolPacket *RemoveQueue(uint16 seq);
|
|
|
|
void _SendDisconnect();
|
|
|
|
void init(bool resetSession=true);
|
|
public:
|
|
EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
|
|
StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2;
|
|
bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0;
|
|
streamactive = false; }
|
|
EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr;
|
|
remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream;
|
|
compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0;
|
|
create_time = Timer::GetTimeSeconds(); }
|
|
virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
|
|
void SetMaxLen(uint32 length) { MaxLen=length; }
|
|
|
|
//interface used by application (EQStreamInterface)
|
|
virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true);
|
|
virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true);
|
|
virtual EQApplicationPacket *PopPacket();
|
|
virtual void Close();
|
|
virtual uint32 GetRemoteIP() const { return remote_ip; }
|
|
virtual uint16 GetRemotePort() const { return remote_port; }
|
|
virtual void ReleaseFromUse() { MInUse.lock(); if(active_users > 0) active_users--; MInUse.unlock(); }
|
|
virtual void RemoveData() { InboundQueueClear(); OutboundQueueClear(); PacketQueueClear(); /*if (CombinedAppPacket) delete CombinedAppPacket;*/ }
|
|
virtual bool CheckState(EQStreamState state) { return GetState() == state; }
|
|
virtual std::string Describe() const { return("Direct EQStream"); }
|
|
|
|
virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; }
|
|
|
|
virtual OpcodeManager* GetOpcodeManager() const
|
|
{
|
|
return (*OpMgr);
|
|
};
|
|
|
|
void CheckTimeout(uint32 now, uint32 timeout=30);
|
|
bool HasOutgoingData();
|
|
void Process(const unsigned char *data, const uint32 length);
|
|
void SetLastPacketTime(uint32 t) {LastPacket=t;}
|
|
void Write(int eq_fd);
|
|
|
|
// whether or not the stream has been assigned (we passed our stream match)
|
|
virtual void SetActive(bool val) { streamactive = val; }
|
|
|
|
//
|
|
inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; }
|
|
inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); }
|
|
|
|
virtual EQStreamState GetState() { EQStreamState s; MState.lock(); s=State; MState.unlock(); return s; }
|
|
|
|
static SeqOrder CompareSequence(uint16 expected_seq , uint16 seq);
|
|
|
|
bool CheckActive() { return GetState()==ESTABLISHED; }
|
|
bool CheckClosed() { return GetState()==CLOSED; }
|
|
void SetOpcodeSize(uint8 s) { app_opcode_size = s; }
|
|
void SetStreamType(EQStreamType t);
|
|
inline const EQStreamType GetStreamType() const { return StreamType; }
|
|
static const char *StreamTypeString(EQStreamType t);
|
|
|
|
void Decay();
|
|
void AdjustRates(uint32 average_delta);
|
|
|
|
uint32 bytes_sent;
|
|
uint32 bytes_recv;
|
|
uint32 create_time;
|
|
|
|
void AddBytesSent(uint32 bytes)
|
|
{
|
|
bytes_sent += bytes;
|
|
++sent_packet_count;
|
|
}
|
|
|
|
void AddBytesRecv(uint32 bytes)
|
|
{
|
|
bytes_recv += bytes;
|
|
++received_packet_count;
|
|
}
|
|
|
|
virtual const uint32 GetBytesSent() const { return bytes_sent; }
|
|
virtual const uint32 GetBytesRecieved() const { return bytes_recv; }
|
|
virtual const uint32 GetBytesSentPerSecond() const
|
|
{
|
|
if((Timer::GetTimeSeconds() - create_time) == 0)
|
|
return 0;
|
|
return bytes_sent / (Timer::GetTimeSeconds() - create_time);
|
|
}
|
|
|
|
virtual const uint32 GetBytesRecvPerSecond() const
|
|
{
|
|
if((Timer::GetTimeSeconds() - create_time) == 0)
|
|
return 0;
|
|
return bytes_recv / (Timer::GetTimeSeconds() - create_time);
|
|
}
|
|
|
|
const uint64 GetPacketsSent() { return sent_packet_count; }
|
|
const uint64 GetPacketsReceived() { return received_packet_count; }
|
|
|
|
//used for dynamic stream identification
|
|
virtual MatchState CheckSignature(const Signature *sig);
|
|
|
|
};
|
|
|
|
#endif
|
|
|