Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1272 lines
40 KiB
C++
1272 lines
40 KiB
C++
#if !defined(__MUGSOCS__)
|
|
#define __MUGSOCS__
|
|
|
|
#define CSOC_SERVER_ID ((UINT)INT_MIN)
|
|
#define CSOC_CLIENT_ID ((UINT)0)
|
|
#define CSOC_LISTEN_ID ((UINT)-1)
|
|
|
|
#if !defined(STATIC_FDARRAY_MAX)
|
|
#define STATIC_FDARRAY_MAX 4
|
|
#endif // !defined(STATIC_FDARRAY_MAX)
|
|
#if STATIC_FDARRAY_MAX < 0
|
|
#error must : STATIC_FDARRAY_MAX >= 0
|
|
#endif
|
|
|
|
#if defined(SR_ASSERT)
|
|
#ifdef ASSERT
|
|
#undef ASSERT
|
|
#endif // ASSERT
|
|
#define ASSERT SR_ASSERT
|
|
#endif // SR_ASSERT
|
|
|
|
#ifndef NULL_CLASS_DEFINED
|
|
#define NULL_CLASS_DEFINED
|
|
class CNullClass {};
|
|
#endif
|
|
|
|
#if !defined(SOCBase_Class)
|
|
#define SOCBase_Class CNullClass
|
|
#endif // !defined(SOCBase_Class)
|
|
|
|
extern char SERVERID[];
|
|
|
|
#ifdef WIN32
|
|
#define ioctl(a,b,c) ioctlsocket(a,b,c)
|
|
#endif
|
|
|
|
//#define CMD_TYPEBREAKER 128
|
|
|
|
#ifndef MAX_PACKET
|
|
#define MAX_PACKET 2048
|
|
#endif // !MAX_PACKET
|
|
#ifndef MAX_FTPBUF
|
|
#define MAX_FTPBUF 1024
|
|
// MAX_FTPBUF는 MAX_PACKET보다 반드시 작아야 한다?
|
|
// 9+size==sizeof(bCmd) + sizeof(FTID) + sizeof(size) + size
|
|
#endif // !MAX_FTPBUF
|
|
|
|
// #define NO_PDCD - define PDCD for - no check PACKET_DUMP_CHECK_DISASSEMBLE - be very cautious!!!
|
|
// #define NO_PDCA - define PDCA for - no check PACKET_DUMP_CHECK_ASSEMBLE - be very cautious???
|
|
|
|
#ifndef MY_LINGER_TIME
|
|
#define MY_LINGER_TIME 250
|
|
#endif // !MY_LINGER_TIME
|
|
|
|
#ifndef RCV_MAX
|
|
#define RCV_MAX 10240
|
|
#endif // !RCV_MAX
|
|
|
|
#ifndef SND_MAX
|
|
#define SND_MAX 10240
|
|
#endif // !SND_MAX
|
|
|
|
#if (SND_MAX < MAX_PACKET) || (RCV_MAX < MAX_PACKET)
|
|
#error Both(SND_MAX & RCV_MAX) >= MAX_PACKET
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#if !defined(NO_USE_OVRIO)
|
|
#define USE_OVRIO
|
|
#endif // !defined(NO_USE_OVRIO)
|
|
#else // !WIN32
|
|
#undef USE_OVRIO
|
|
#endif // WIN32
|
|
//#undef USE_OVRIO
|
|
|
|
#define PUSHFLOAT(f) (*(DWORD*)&(f))
|
|
|
|
enum EException
|
|
{
|
|
EEXCP_NoError,
|
|
|
|
// local side...
|
|
EEXCP_TooLowVersion,
|
|
EEXCP_Unknown,
|
|
EEXCP_ConnectionTimeOut,
|
|
EEXCP_ConnectionFailure,
|
|
EEXCP_SendBufferOverflow,
|
|
EEXCP_VersionError,
|
|
|
|
// fatal socket error...
|
|
EEXCP_WSAENETDOWN,
|
|
EEXCP_WSANO_RECOVERY,
|
|
EEXCP_WSAENETRESET,
|
|
EEXCP_WSAECONNRESET,
|
|
EEXCP_WSAECONNABORTED,
|
|
EEXCP_WSAEADDRINUSE,
|
|
EEXCP_WSAETIMEDOUT,
|
|
EEXCP_WSAEHOSTUNREACH,
|
|
EEXCP_WSAEACCES,
|
|
|
|
// internal error
|
|
EEXCP_WSANOTINITIALISED,
|
|
EEXCP_WSAEFAULT,
|
|
EEXCP_WSAENOTSOCK,
|
|
EEXCP_WSAENOTCONN,
|
|
EEXCP_WSAEOPNOTSUPP,
|
|
EEXCP_WSAEINVAL,
|
|
EEXCP_DupCreation,
|
|
};
|
|
|
|
#if !defined(STRF_MAX_PARAMS)
|
|
#define STRF_MAX_PARAMS 7 // should be 3 or 7
|
|
#endif
|
|
#if !((STRF_MAX_PARAMS==3) || (STRF_MAX_PARAMS==7))
|
|
#error STRF_MAX_PARAMS size must be 3 or 7...
|
|
#endif
|
|
|
|
const char* SkipWord(const char* pcsz);
|
|
const char* SkipWhite(const char* pcsz);
|
|
const char* SkipWhiteReverse(const char* pcsz);
|
|
BOOL IsControlExist(const char* pcsz);
|
|
BOOL IsAllDigit(const char* pcsz);
|
|
BOOL CheckStringOK(const char* pcsz, int nMin, int nMax);
|
|
BOOL CheckNumberOK(const char* pcsz, int nMin, int nMax);
|
|
BOOL IsInvalidCharsExist(const char* pcsz, const char* pcszInvalidChars);
|
|
char* cmd_GetString(char*& psz, int nQuoteType = 0);
|
|
int cmd_GetNumber(char*& psz, int& nNumber, int nMin = 0, int nMax = 65536);
|
|
|
|
#ifdef WIN32
|
|
#pragma pack(push, 1)
|
|
#endif // WIN32
|
|
DECLARE_TARRAYREF(CTEXTFmt);
|
|
|
|
class CTEXTFmt : public CStr
|
|
{
|
|
public:
|
|
union {
|
|
struct {
|
|
WORD m_wFmt;
|
|
WORD m_wTX;
|
|
} m_DW;
|
|
DWORD m_dw;
|
|
};
|
|
char m_caParamType[STRF_MAX_PARAMS + 1];
|
|
public:
|
|
CTEXTFmt(const char* pcszFormat = NULL);
|
|
};
|
|
#ifdef WIN32
|
|
#pragma pack(pop)
|
|
#endif // WIN32
|
|
|
|
class CTEXTFmtArray : public TARRAYREF(CTEXTFmt)
|
|
{
|
|
public:
|
|
class CAtoms : public TARRAYREF(CStr)
|
|
{
|
|
public:
|
|
CStr m_strTitle;
|
|
public:
|
|
CAtoms(const char* pcsz)
|
|
: m_strTitle(pcsz)
|
|
{
|
|
SetGrowBy(10);
|
|
}
|
|
};
|
|
TARRAYPTR(CAtoms*) m_paAtoms;
|
|
public:
|
|
CTEXTFmtArray();
|
|
virtual ~CTEXTFmtArray();
|
|
int LoadFmts(const char* pcszFile, const char* pcszSignature, BOOL bCheckACP = FALSE);
|
|
CTEXTFmt& FindTEXTFmt(WORD wFmt) const;
|
|
CAtoms* FindAtoms(const char* pcsz) const;
|
|
void Sort();
|
|
private:
|
|
int ProcessOneLine(BYTE baLine[], const char* pcszSignature, int nSizeOld, int nSize);
|
|
CTEXTFmt& FindOnLoad(WORD wFmt, int nSizeOld, int nSize) const;
|
|
static void ProcessEscape(BYTE* pb);
|
|
};
|
|
|
|
#define ESTRF_OK 0 // no error
|
|
#define ESTRF_ERR (-1)
|
|
|
|
// Login Error
|
|
#define ESTRF_VERSIONERROR 10
|
|
#define ESTRF_RESTART_PROGRAM 11
|
|
#define ESTRF_TOOMANY_CONNECTIONS 12
|
|
#define ESTRF_INVALIDLOGININFO 13 // C_LOGN_INFO invalid id or password
|
|
#define ESTRF_INVALIDLOGINNAME 14 // C_LOGN_INFO
|
|
#define ESTRF_INVALIDPASSWORD 15 // C_LOGN_INFO, C_ROOM_JOIN
|
|
#define ESTRF_ALREADYLOGIN 16 // C_LOGN_INFO
|
|
#define ESTRF_SAMEUSEREXIST 17 // C_USER_INFO
|
|
#define ESTRF_NOSUCHUSER 18 // C_USER_INFO
|
|
#define ESTRF_NAME 19 // C_USER_INFO
|
|
#define ESTRF_EMAIL 20 // C_USER_INFO
|
|
#define ESTRF_DATEBORN 21 // C_USER_INFO
|
|
#define ESTRF_HOMEPAGE 22 // C_USER_INFO
|
|
|
|
// DB error
|
|
#define ESTRF_DBCONNECTION 30 // C_LOGN_INFO
|
|
#define ESTRF_DBOPEN 31 // C_LOGN_INFO
|
|
#define ESTRF_DBRESTART 32 // C_LOGN_INFO
|
|
#define ESTRF_DBACCESS 33 // C_LOGN_INFO
|
|
|
|
// Room Error
|
|
#define ESTRF_TOOMANYROOMS 40 // C_ROOM_MAKE
|
|
#define ESTRF_SAMEROOMEXIST 41 // C_ROOM_MAKE
|
|
#define ESTRF_NOSUCHROOM 42 // C_ROOM_JOIN
|
|
#define ESTRF_ALREADYINROOM 43 // C_ROOM_JOIN
|
|
#define ESTRF_NOOTHERUSERS_IN_ROOM 44
|
|
#define ESTRF_TOOMANYUSERS_IN_ROOM 45 // C_ROOM_JOIN
|
|
#define ESTRF_INVALID_ROOMNAME 46 // C_ROOM_JOIN...
|
|
#define ESTRF_INVALID_ROOMPASSWORD 47 // C_ROOM_JOIN...
|
|
#define ESTRF_INVALID_MAX 48 // C_ROOM_MAKE
|
|
#define ESTRF_ROOM_STAT 49 // C_ROOM_STAT
|
|
|
|
// Plyr Error
|
|
#define ESTRF_OWNERCOMMAND 50
|
|
#define ESTRF_KICKEDBYOWNER 51
|
|
#define ESTRF_BANISHIEDBYOWNER 52
|
|
#define ESTRF_YOUAREALREADYBANISHIED 53
|
|
#define ESTRF_NOSUCHUSERINROOM 54
|
|
#define ESTRF_NOOWNERCOMMAND_TO_USER_INANOTHERROOM 55
|
|
#define ESTRF_OWNER_CHANGED 56
|
|
#define ESTRF_OWNER_CHANGED_AUTO 57
|
|
#define ESTRF_PLYR_IS_THERE 58
|
|
#define ESTRF_PLYR_NOT_LOGGED 59
|
|
#define ESTRF_PLYR_IS_THERE_LONELY 60
|
|
#define ESTRF_NOP_ON_SELF 61
|
|
#define ESTRF_JOIN_ANYROOM 62
|
|
#define ESTRF_NO_INVITATION_TO_USER_IN_SAME_ROOM 63
|
|
#define ESTRF_INVITATION_CALLED 64
|
|
#define ESTRF_INVITATION_CALLED_BY_OTHER 65
|
|
#define ESTRF_INVITER_LOGGEDOUT 66
|
|
#define ESTRF_INVITER_MOVED_ROOM 67
|
|
#define ESTRF_INVITATION_CHECK_ERROR 68
|
|
#define ESTRF_INVITITATION_ABORTED 69
|
|
#define ESTRF_INVITATION_DENIED 70
|
|
#define ESTRF_USER_BANISHIED 71
|
|
#define ESTRF_USER_KICKED 72
|
|
#define ESTRF_EX_ON 73
|
|
#define ESTRF_EX_OFF 74
|
|
#define ESTRF_YOUARE_SQUELDED_BY 75
|
|
#define ESTRF_USER_IS_NOT_RESPONDING 76
|
|
#define ESTRF_ALREADY_SQUELED 77
|
|
#define ESTRF_XSQUELED 78
|
|
#define ESTRF_YOUARE_XSQUELED_BY 79
|
|
#define ESTRF_SQUELED 80
|
|
#define ESTRF_YOUARE_SQUELED_BY 81
|
|
#define ESTRF_ALREADY_XSQUELED 82
|
|
#define ESTRF_SQUEL_COUNT_DROP 83
|
|
|
|
#define ESTRF_USER_START 100
|
|
|
|
#define ESTRF_PASSWORDCHANGED 110 // 로그인하고 있는 동안에 패스워드가 바뀜
|
|
|
|
void Randomize();
|
|
|
|
union UPacketValue
|
|
{
|
|
// CPU register specific
|
|
WORD m_w;
|
|
DWORD m_dw;
|
|
float m_f;
|
|
double m_dbl;
|
|
SINT64 m_i64;
|
|
};
|
|
#define UPKV(pbPacket) ((UPacketValue*)(pbPacket))
|
|
|
|
class CDAPacket : public SOCBase_Class
|
|
{
|
|
// Packet의 앞 부분을 처리하고 난 뒷 부분의 가변 파라미터...
|
|
public:
|
|
BYTE m_bCmd;
|
|
BYTE m_bReserved;
|
|
WORD m_wLen;
|
|
BYTE* m_pbPacket;
|
|
public:
|
|
virtual CSOC* IsSOC() const { return NULL; }
|
|
DWORD Push() const;
|
|
void Pop(DWORD dw);
|
|
BYTE* GetData(int nSize);
|
|
BYTE* __cdecl Disassemble(const char* pcszFormat, ...);
|
|
BYTE* __cdecl vDisassemble(const char* pcszFormat, va_list ap);
|
|
};
|
|
|
|
#define CSCODE_OK 0
|
|
#define CSCODE_ERR 0xff
|
|
|
|
#define CSCODE_CREATE 0
|
|
#define CSCODE_ADDED CSCODE_CREATE
|
|
#define CSCODE_INFO 2
|
|
#define CSCODE_CHANGE 3
|
|
#define CSCODE_CHANGED CSCODE_CHANGE
|
|
#define CSCODE_DELETE 4
|
|
#define CSCODE_DELETED CSCODE_DELETE
|
|
|
|
#define CSCODE_WHERE 5
|
|
#define CSCODE_SAY 6
|
|
#define CSCODE_INVITE 7
|
|
#define CSCODE_INVITE_RESULT 8
|
|
#define CSCODE_TO 9
|
|
#define CSCODE_SQUEL 10
|
|
#define CSCODE_XSQUEL 11
|
|
#define CSCODE_EX 12 // dummy user...
|
|
#define CSCODE_KICK 13 // C_PLYR_ACTN...
|
|
#define CSCODE_BANISH 14 // C_PLYR_ACTN...
|
|
#define CSCODE_CHOWNER 15 // C_PLYR_ACTN...
|
|
|
|
#define CSCODE_TITLE 20
|
|
#define CSCODE_PASSWORD 21
|
|
#define CSCODE_MAX 23
|
|
|
|
#define CSCODE_START 0xfa
|
|
#define CSCODE_MORE 0xfb
|
|
#define CSCODE_STOP 0xfc
|
|
|
|
#define S_PROG_INFO 200
|
|
#define C_PROG_INFO 200
|
|
// D - dwVersion
|
|
|
|
#define S_LOGN_INFO 210
|
|
#define C_LOGN_INFO 210
|
|
// s - ID, s - Password
|
|
#define S_LOGN_RSLT 211
|
|
// b - code(CSCODE_OK - ok or error code)
|
|
|
|
#define C_USER_INFO 215
|
|
// b - code(CSCODE_CREATE/CSCODE_INFO/CSCODE_CHANGE/CSCODE_DELETE), s - ID, s - Password...
|
|
#define S_USER_RSLT 215
|
|
// b - code(same w/ C_USER_INFO or CSCODE_ERR_...) if (code == CSCODE_INFO) additional user infos...
|
|
|
|
#define S_PLYR_INFO 220
|
|
// b - code(CSCODE_ADDED/CSCODE_CHANGED/CSCODE_DELETED/CSCODE_START/CSCODE_STOP), s - name, ...
|
|
#define C_PLYR_INFO 220
|
|
// b - code(CSCODE_NEXT/CSCODE_START/CSCODE_STOP)
|
|
#define C_PLYR_STAT 221
|
|
// s - name
|
|
#define S_PLYR_STAT 221
|
|
// b - code(CSCODE_OK - ok or error code)
|
|
#define C_PLYR_ACTN 222
|
|
// b - code(CSCODE_INFO, CSCODE_KICK, CSCODE_BANISH), s - name, ...
|
|
#define S_PLYR_ACTN 222
|
|
// b - code(CSCODE_KICK)
|
|
|
|
#define S_SRVR_INFO 225
|
|
// b - code(CSCODE_ADDED/CSCODE_CHANGED/CSCODE_DELETED/CSCODE_START/CSCODE_STOP), d - number, s - name, ...
|
|
#define C_SRVR_INFO 225
|
|
// b - code(CSCODE_NEXT/CSCODE_START/CSCODE_STOP)
|
|
#define C_SRVR_STAT 226
|
|
// d - name
|
|
#define S_SRVR_STAT 226
|
|
// b - code(CSCODE_OK - ok or error code)
|
|
|
|
#define S_ROOM_INFO 230
|
|
// b - code(CSCODE_ADDED/CSCODE_CHANGED/CSCODE_DELETED/CSCODE_START/CSCODE_STOP), d - number, s - name, b - Password exist, w - user count...
|
|
#define C_ROOM_INFO 230
|
|
// b - code(CSCODE_NEXT/CSCODE_START/CSCODE_STOP)
|
|
#define C_ROOM_STAT 231 // room number
|
|
#define S_ROOM_STAT 231
|
|
// b - code(CSCODE_OK - ok or error code)
|
|
#define C_ROOM_MAKE 232
|
|
// s - name, s - password
|
|
#define C_ROOM_JOIN 233
|
|
// d - number(Room을 떠나는 것은 -1), s - password
|
|
#define S_ROOM_JOIN 233 // C_ROOM_MAKE/C_ROOM_JOIN의 결과...
|
|
// b - code(CSCODE_OK or error code), d - number
|
|
#define C_ROOM_UPDS 234 // CSCODE_... + @
|
|
|
|
#define S_GAME_INFO 235
|
|
// b - code(CSCODE_ADDED/CSCODE_CHANGED/CSCODE_DELETED/CSCODE_START/CSCODE_STOP), d - number, s - name, ...
|
|
#define C_GAME_INFO 235
|
|
// b - code(CSCODE_NEXT/CSCODE_START/CSCODE_STOP)
|
|
#define C_GAME_STAT 236
|
|
// d - name
|
|
#define S_GAME_STAT 236
|
|
// b - code(CSCODE_OK - ok or error code)
|
|
#define C_GAME_RSLT 237
|
|
|
|
// same server/client command...
|
|
#define X_TEXT 250 // %s{Sender/Receiver ID}%s{notify string}%W{TX_...}
|
|
#define X_TEXTFMT 251 // %W{Format}%s{ParamFormat}[{params0}[{params2}[...]]]
|
|
|
|
#define C_FTP 253 //... see ftp.txt
|
|
#define S_FTP 254 //... see ftp.txt
|
|
#define X_KEEPALIVE 255 // no parameters, should be ignored...
|
|
|
|
#define TX_SYSTEM 0 // 시스템 메시지...
|
|
#define TX_NORMAL 1 // 일반 채팅 텍스트
|
|
#define TX_WARNING 2 // 경고
|
|
#define TX_ERROR 3 // 오류
|
|
#define TX_FATAL 4 // 치명적인 오류
|
|
#define TX_INFO 5 // 사용자 정보 등의 Information Result...
|
|
#define TX_SAY 6 // 귓속말
|
|
#define TX_LOCAL 7 // local echo....
|
|
#define TX_UNKNOWN 0xffff // unknown...
|
|
|
|
typedef long (*PFN_TimerProc)(CTimerEvent& Timer);
|
|
|
|
class CSOCListen;
|
|
class CSOCClient;
|
|
typedef CSOCClient* (*PFN_CreateSOCClient)(const CSOCListen& SOCListen, DWORD dwCSCParam1, DWORD dwCSCParam2);
|
|
|
|
#ifdef WIN32
|
|
#pragma pack(push, 1)
|
|
#endif // WIN32
|
|
class CTimerEvent
|
|
{
|
|
friend class CTimerPool;
|
|
public:
|
|
PFN_TimerProc m_pfnTimerProc;
|
|
DWORD m_dwTime;
|
|
void* m_pVoid;
|
|
// no function params...
|
|
int m_nParam; // not initialized...
|
|
DWORD m_dwParam; // not initialized...
|
|
protected:
|
|
DWORD m_dwFrame;
|
|
};
|
|
#ifdef WIN32
|
|
#pragma pack(pop)
|
|
#endif // WIN32
|
|
|
|
#define CHK_TIMER_NOVOIDCHECK 0x8000
|
|
#define CHK_TIMER_ONCE 0x0001
|
|
|
|
class CTimerPool : public TARRAY(CTimerEvent)
|
|
{
|
|
private:
|
|
int m_nReEnter;
|
|
public:
|
|
BOOL m_bDirty;
|
|
protected:
|
|
DWORD m_dwPrecision;
|
|
DWORD m_dwLastTicks;
|
|
private:
|
|
DWORD m_dwFrame;
|
|
public:
|
|
CTimerPool();
|
|
public:
|
|
DWORD GetPrecision() const { return m_dwPrecision; }
|
|
void SetPrecision(DWORD dwPrecision) { m_dwPrecision = dwPrecision; }
|
|
DWORD GetLastTicks() const { return m_dwLastTicks; }
|
|
void SetLastTicks(DWORD dwLastTicks) { m_dwLastTicks = dwLastTicks; }
|
|
public:
|
|
void CheckTimers();
|
|
CTimerEvent& AddTimer(PFN_TimerProc pfnTimerProc, DWORD dwTime, void* pVoid);
|
|
BOOL DelTimer(int nIndex);
|
|
BOOL DelTimers(PFN_TimerProc pfnTimerProc, void* pVoid, UINT uFlags, int nFromIndex = 0);
|
|
BOOL DelTimersAll() { return DelTimers((PFN_TimerProc)NULL, NULL, 0, 0); }
|
|
int FindTimer(PFN_TimerProc pfnTimerProc, void* pVoid, UINT uFlags, int nFromIndex = 0);
|
|
};
|
|
|
|
union UFmtParam
|
|
{
|
|
// CPU register specific
|
|
BYTE m_b; // 'B'
|
|
unsigned char m_c; // 'b'
|
|
WORD m_w; // 'W'
|
|
short m_s; // 'w'
|
|
int m_n; // 'n'
|
|
long m_l; // 'd'
|
|
DWORD m_dw; // 'D'
|
|
float m_f;
|
|
double m_F;
|
|
char* m_psz; // 's' or 'S' - don't mix...
|
|
SINT64 m_i64; // '6' - 64 bit integer...
|
|
// 'x' - binary data, wLen + Data
|
|
// 'X' - mainly for Assemble, sub-packet copy... no info for disassemble
|
|
// '!' - CPacketDumper*
|
|
};
|
|
|
|
class CPacketDumper
|
|
{
|
|
public:
|
|
public:
|
|
CPacketDumper() {}
|
|
virtual ~CPacketDumper() {}
|
|
virtual BYTE* Disassemble(BYTE* pbPacket, BYTE* pbPacketEnd) = 0;
|
|
virtual BYTE* Assemble(BYTE* pbPacket, BYTE* pbPacketEnd) = 0;
|
|
};
|
|
|
|
#ifdef WIN32
|
|
#pragma pack(push, 1)
|
|
#endif // WIN32
|
|
DECLARE_TARRAYREF(CPacket)
|
|
class
|
|
#ifdef WIN32
|
|
__declspec(novtable)
|
|
#endif // WIN32
|
|
CPacket
|
|
{
|
|
friend class CSOCConnect;
|
|
protected:
|
|
CSOC* m_pSOC;
|
|
private:
|
|
// 이 안의 블럭은 반드시 연속해야 한다...
|
|
WORD m_wLen;
|
|
BYTE m_ba[MAX_PACKET];
|
|
//
|
|
public:
|
|
CPacket(CSOC* pSOC);
|
|
~CPacket();
|
|
void Reset();
|
|
CSOC& GetSOC() const { ASSERT(this); return *m_pSOC; }
|
|
const BYTE* GetPacketStart() const { return (const BYTE*)&m_wLen; }
|
|
int GetLength() const { return m_wLen; }
|
|
void SetLength(int nLen) { m_wLen = (WORD)(short)nLen; }
|
|
BYTE* GetBuffer() const { return (BYTE*)&m_ba[0]; }
|
|
int GetTotalLength() const { return sizeof(WORD) + m_wLen; }
|
|
BYTE* GetLastPtr() const { return (BYTE*)&m_ba[m_wLen]; }
|
|
BYTE* GetEndPtr() const { return (BYTE*)&m_ba[MAX_PACKET]; }
|
|
void Prepare(int nSize) { m_wLen += (WORD)nSize; }
|
|
BYTE* __cdecl Assemble(const char* pcszFormat, ...);
|
|
BYTE* __cdecl vAssemble(const char* pcszFormat, va_list ap);
|
|
BYTE* DisassembleParamsAndTextFmt(CSOCConnect& SOC, WORD wFmt, const char* pcszParamType, WORD& wTX);
|
|
protected:
|
|
void DropSOC();
|
|
BYTE* DoTextFmt(const char* pcszFormat, const UFmtParam aFPs[STRF_MAX_PARAMS], const char caParamType[/*STRF_MAX_PARAMS + 1*/]);
|
|
};
|
|
#ifdef WIN32
|
|
#pragma pack(pop)
|
|
#endif // WIN32
|
|
|
|
class CSockAddr : public sockaddr_in
|
|
{
|
|
public:
|
|
CStr m_strTarget;
|
|
public:
|
|
CSockAddr(int nPort, const char* pcszAddr = NULL, short sFamily = AF_INET);
|
|
CSockAddr(int nPort, u_long ulAddr = INADDR_ANY, short sFamily = AF_INET);
|
|
public:
|
|
sockaddr_in* GetSockAddrIn() { return this; }
|
|
const char* GetTarget() const;
|
|
u_long GetTargetAddr() const { return ntohl(sin_addr.s_addr); }
|
|
void SetTarget(const char* pcszAddr);
|
|
void SetTarget(u_long ulAddr);
|
|
int GetPort() const;
|
|
void SetPort(int nPort);
|
|
};
|
|
const char* GetHostAddress();
|
|
|
|
typedef void (CSOC::*PF_PacketProcessor)();
|
|
#define PFPP_CallBase ((PF_PacketProcessor)0) // do not change this line...
|
|
#define PFPP_Ignore CSOC::OnIgnore // why not? ((PF_PacketProcessor)1)
|
|
|
|
#define MAX_PACKET_TYPE 256 // 1byte
|
|
|
|
/****************
|
|
start of variable PACKET_MAP definitions...
|
|
****************/
|
|
|
|
struct _SPacketMap
|
|
{
|
|
public:
|
|
_SPacketMap* m_pBaseMap;
|
|
PF_PacketProcessor* m_pPFPP;
|
|
public:
|
|
PF_PacketProcessor TraceAndModifyBaseCall(BYTE bCmd, PF_PacketProcessor& refPFPP) const;
|
|
};
|
|
|
|
#define PACKET_MAP(CLASSNAME) _CAutoStart##CLASSNAME
|
|
#define PACKET_MAP_STATIC_INSTANCE(CLASSNAME) _g_AutoStart##CLASSNAME##Instance
|
|
|
|
#define DECLARE_PACKET_MAP(thisClass) friend class PACKET_MAP(thisClass); protected: static PF_PacketProcessor m_aPFPP[MAX_PACKET_TYPE]; static _SPacketMap m_PacketMap; protected: virtual _SPacketMap* GetPacketMap() const;
|
|
|
|
// start of BEGIN_PACKET_MAP_RAW, BEGIN_PACKET_MAP
|
|
#define BEGIN_PACKET_MAP_RAW(thisClass, basePacketMap) PF_PacketProcessor thisClass::m_aPFPP[MAX_PACKET_TYPE] = { PFPP_CallBase, }; _SPacketMap thisClass::m_PacketMap = { basePacketMap, &thisClass::m_aPFPP[0] }; _SPacketMap* thisClass::GetPacketMap() const { return &thisClass::m_PacketMap; } class PACKET_MAP(thisClass) { public: PACKET_MAP(thisClass)() {
|
|
|
|
#define BEGIN_PACKET_MAP(thisClass, baseClass) BEGIN_PACKET_MAP_RAW(thisClass, &baseClass::m_PacketMap)
|
|
// end of BEGIN_PACKET_MAP_RAW, BEGIN_PACKET_MAP
|
|
|
|
// start of PACKET_MAP_ENTRY_RAW, PACKET_MAP_ENTRY, PACKET_MAP_ENTRY_IGNORE
|
|
#define PACKET_MAP_ENTRY_RAW(thisClass, bCmd, PFPP) ASSERT((0 <= bCmd) && (bCmd < MAX_PACKET_TYPE)); thisClass::m_aPFPP[bCmd] = (PF_PacketProcessor)&PFPP;
|
|
#define PACKET_MAP_ENTRY(thisClass, bCmd, PFPP) PACKET_MAP_ENTRY_RAW(thisClass, bCmd, thisClass::PFPP)
|
|
|
|
#define PACKET_MAP_ENTRY_IGNORE(thisClass, bCmd) PACKET_MAP_ENTRY_RAW(thisClass, bCmd, PFPP_Ignore)
|
|
// end of PACKET_MAP_ENTRY & PACKET_MAP_ENTRY_IGNORE
|
|
|
|
// start of END_PACKET_MAP
|
|
#define END_PACKET_MAP(thisClass) } }; static PACKET_MAP(thisClass) PACKET_MAP_STATIC_INSTANCE(thisClass);
|
|
// end of END_PACKET_MAP
|
|
|
|
/****************
|
|
end of variable PACKET_MAP definitions...
|
|
****************/
|
|
|
|
class CFileTransfer : public TDBLNK(CFileTransfer*)
|
|
{
|
|
public:
|
|
// 서버로 부터 받은 정보... - 혹은 클라이언트에게 전해줄 정보...
|
|
BOOL m_bClientSite;
|
|
DWORD m_dwFTID;
|
|
DWORD m_dwGUARD;
|
|
CStr m_strFileNameRemote;
|
|
DWORD m_dwTime;
|
|
long m_lSize;
|
|
|
|
UINT m_uMinBPS;
|
|
UINT m_uMaxBPS;
|
|
CStr m_strFileNameLocal;
|
|
int m_nFile;
|
|
long m_lPos;
|
|
DWORD m_dwStartTime;
|
|
public:
|
|
CFileTransfer(DWORD dwFTID, DWORD dwGUARD, const char* pcszFileNameRemote, const char* pcszFileNameLocal);
|
|
virtual ~CFileTransfer();
|
|
virtual BOOL Setup(DWORD& dwError);
|
|
virtual BOOL Setup(DWORD dwTime, long lSize, DWORD& dwError);
|
|
virtual int CheckReadPosition(long lPosition) const;
|
|
int Close();
|
|
void Start();
|
|
};
|
|
|
|
class CFTPArray : TARRAY(CFileTransfer*)
|
|
{
|
|
public:
|
|
public:
|
|
CFTPArray();
|
|
virtual ~CFTPArray();
|
|
int Find(CFileTransfer* pFTP) const;
|
|
CFileTransfer* CutIfExist(CFileTransfer* pFTP);
|
|
};
|
|
|
|
#ifdef USE_OVRIO
|
|
DECLARE_TARRAYREF(COVRIO);
|
|
#ifdef WIN32
|
|
#pragma pack(push, 1)
|
|
#endif // WIN32
|
|
class
|
|
#ifdef WIN32
|
|
__declspec(novtable)
|
|
#endif // WIN32
|
|
COVRIO : public TDoubleLinkRef<COVRIO*, WSAOVERLAPPED>
|
|
{
|
|
public:
|
|
CSOC* m_pSOC;
|
|
int m_nSize;
|
|
BYTE m_ba[/*m_nSize*/];
|
|
public:
|
|
COVRIO();
|
|
~COVRIO();
|
|
DECLARE_STATIC_CONSTRUCTION(COVRIO);
|
|
};
|
|
#ifdef WIN32
|
|
#pragma pack(pop)
|
|
#endif // WIN32
|
|
COVRIO* newCOVRIO(CSOC* pSOC, const BYTE* pb, int nSize);
|
|
void deleteCOVRIO(COVRIO* pOVRIO);
|
|
void CALLBACK OVRIO_Completion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
|
|
#endif // USE_OVRIO
|
|
|
|
#define SOCNEXT_EXCCLIENT 0x0001
|
|
#define SOCNEXT_EXCSERVER 0x0002
|
|
#define SOCNEXT_EXCLISTEN 0x0004
|
|
|
|
#define SOCNEXT_EXCINVALID 0x0010
|
|
#define SOCNEXT_EXCDROPPING 0x0020
|
|
#define SOCNEXT_EXCCONNECTTING 0x0080 // CSOCServer Only...
|
|
|
|
#define SOCNEXT_CHECKPROC 0x4000
|
|
#define SOCNEXT_REVERSE 0x8000
|
|
|
|
#define SOCNEXT_DEFAULT (SOCNEXT_EXCINVALID|SOCNEXT_EXCDROPPING|SOCNEXT_EXCLISTEN|SOCNEXT_EXCCONNECTTING)
|
|
|
|
class CSOC : public CDAPacket
|
|
{
|
|
friend class CSOCManager;
|
|
DECLARE_PACKET_MAP(CSOC)
|
|
protected:
|
|
int m_nLockCount;
|
|
|
|
SOCKET m_hSocket;
|
|
int m_nState;
|
|
BOOL m_bSendLoop;
|
|
CSOCManager* m_pSOCManager;
|
|
CSockAddr m_Addr;
|
|
// time - last Rcv/Snd
|
|
DWORD m_dwKARcvTicks;
|
|
DWORD m_dwKASndTicks;
|
|
// time out to Drop...
|
|
DWORD m_dwKARcvTimeOut;
|
|
#ifdef WIN32
|
|
// 보통 Login과정에 쓰이는 윈도우 핸들
|
|
HWND m_hWndOwner;
|
|
#endif // WIN32
|
|
// 보통 글로벌 변수로 쓰이는 소켓포인터에 대한 자동 NULL Assign을 위하여
|
|
PSOC* m_ppSOC;
|
|
// 소켓을 구분하기 위하여 사용자 프로그램에서 쓰이는 아이디
|
|
// 주로 서버의 경우에는 클라이언트가 접속할 때마다 고유 아이디를 부여하여 사용
|
|
// 하나의 Client가 다수의 서버에 접속할 때(주로 Star형) 각각의 접속을 구분할 때 사용
|
|
// 클라이언트가 하나의 서버에만 접속하는 경우 클라이언트가 서버에 접속 중인지 혹은 접속했는지를 판단할 때
|
|
// CSOCManager::FindSOC(CSOC_SERVER_ID==default)->GetConnectionState()를 사용.
|
|
// limits.h를 include해야함.
|
|
// CSOC생성시의 기본값: CSOCServer == CSOC_SERVER_ID(=INT_MIN), CSOCClient == CSOC_CLIENT_ID(=0), CSOCListen == CSOC_LISTEN_ID(=-1)
|
|
union {
|
|
int m_nID;
|
|
UINT m_uID;
|
|
void* m_pvID;
|
|
} m_ID;
|
|
protected:
|
|
DWORD m_dwDroppingTicks;
|
|
public:
|
|
TDeQueueFixed<BYTE,RCV_MAX, CNullClass> m_aRcv;
|
|
#ifdef USE_OVRIO
|
|
COVRIO* m_pOVRIOStart;
|
|
#else // !USE_OVRIO
|
|
TDeQueueFixed<BYTE,SND_MAX, CNullClass> m_aSnd;
|
|
#endif // USE_OVRIO
|
|
protected:
|
|
// don't use this - use get/set functions only...
|
|
union {
|
|
struct {
|
|
DWORD m_xAllowAccept: 1; // CSOCListen Only...
|
|
DWORD m_xUseSelect: 1; // Use select() for Acception Check...
|
|
DWORD m_xAutoDelete: 1;
|
|
DWORD m_xAdded: 1;
|
|
DWORD m_xIsConnected: 1;
|
|
DWORD m_xIsConnecting: 1;
|
|
DWORD m_xDoDelSocket: 1;
|
|
DWORD m_xIsDropping: 1;
|
|
DWORD m_xIsSetupFailure: 1;
|
|
DWORD m_xGracefulLocal: 1;
|
|
DWORD m_xErrSEND: 1;
|
|
DWORD m_xErrRECEIVE: 1;
|
|
DWORD m_xGracefulRemote: 1;
|
|
DWORD m_xAbortyLocal: 1;
|
|
DWORD m_xAbortyRemote: 1;
|
|
DWORD m_xLoginStarted: 1; // 사용자가 직접 값을 Setting해야 한다.
|
|
DWORD m_xLoginOK: 1; // 사용자가 직접 값을 Setting해야 한다.
|
|
} m_DW;
|
|
DWORD m_dwVarFlags;
|
|
};
|
|
public:
|
|
CSOC();
|
|
virtual ~CSOC();
|
|
void Reset();
|
|
public:
|
|
operator SOCKET () const { return m_hSocket; }
|
|
SOCKET GetSocket() const { return m_hSocket; }
|
|
BOOL IsValidSafe() const { return this && (m_hSocket != INVALID_SOCKET); }
|
|
BOOL IsValid() const { return m_hSocket != INVALID_SOCKET; }
|
|
int GetID() const { return m_ID.m_nID; }
|
|
void SetID(int nID) { m_ID.m_nID = nID; }
|
|
void Lock() { m_nLockCount++; }
|
|
void Unlock() { ASSERT(m_nLockCount > 0); m_nLockCount--; }
|
|
int GetLockCount() const { return m_nLockCount; }
|
|
BOOL IsConnecting() const { return m_DW.m_xIsConnecting; }
|
|
BOOL IsConnected() const { return m_DW.m_xIsConnected; }
|
|
BOOL IsDroppingState() const { return m_DW.m_xIsDropping; }
|
|
CSockAddr& GetSockAddr() const { return *(CSockAddr*)&m_Addr; }
|
|
void SetRcvTimeOut(DWORD dwTimeOut) { m_dwKARcvTimeOut = dwTimeOut; }
|
|
#ifdef WIN32
|
|
HWND GetOwnerHWND() const { return m_hWndOwner; }
|
|
void SetOwnerHWND(HWND hWndOwner) { m_hWndOwner = hWndOwner; }
|
|
#endif // WIN32
|
|
PSOC* GetSOCPP() const { return m_ppSOC; }
|
|
void SetSOCPP(PSOC* ppSOC) { if (this) m_ppSOC = ppSOC; }
|
|
BOOL GetLoginStarted() const { return m_DW.m_xLoginStarted; }
|
|
void SetLoginStarted(BOOL bLoginStarted) { m_DW.m_xLoginStarted = !!bLoginStarted; }
|
|
BOOL GetLoginOK() const { return m_DW.m_xLoginOK; }
|
|
void SetLoginOK(BOOL bLoginOK) { m_DW.m_xLoginOK = !!bLoginOK; }
|
|
BOOL GetUseSelect() const { return m_DW.m_xUseSelect; }
|
|
void SetUseSelect(BOOL bUseSelect) { m_DW.m_xUseSelect = !!bUseSelect; }
|
|
BOOL GetSendLoop() const { return m_bSendLoop; }
|
|
void SetSendLoop(BOOL bSendLoop) { m_bSendLoop = bSendLoop; }
|
|
const char* GetTarget() const { return m_Addr.m_strTarget; }
|
|
void SetTarget(const char* pcszTarget) { m_Addr.SetTarget(pcszTarget); }
|
|
void SetTarget(u_long ulAddr) { m_Addr.SetTarget(ulAddr); }
|
|
int GetPort() const { return m_Addr.GetPort(); }
|
|
void SetPort(int nPort) { m_Addr.SetPort(nPort); }
|
|
BOOL GetAutoDelete() const { return m_DW.m_xAutoDelete; }
|
|
void SetAutoDelete(BOOL bAutoDelete) { m_DW.m_xAutoDelete = !!bAutoDelete; }
|
|
int GetState() const { return m_nState; }
|
|
void SetState(int nState) { m_nState = nState; }
|
|
CSOCManager& GetSOCManager() const { return *m_pSOCManager; }
|
|
void SetSOCManager(CSOCManager* pSOCManager) { ASSERT(!m_pSOCManager || !pSOCManager); m_pSOCManager = pSOCManager; }
|
|
BOOL IsAdded() const { return m_DW.m_xAdded; }
|
|
void SetAdded(BOOL bAdded) { m_DW.m_xAdded = !!bAdded; }
|
|
CFileTransfer* FindFTP(DWORD dwFTID) const;
|
|
CFileTransfer* FindFTP(const char* pcszFileNameRemote) const;
|
|
public:
|
|
int GetSignatureFromPort(int nPort) const;
|
|
int GetConnectionState() const;
|
|
void Drop();
|
|
public:
|
|
BOOL DoSend(const BYTE* pbBuf, int nSize);
|
|
BOOL DoSendCmdWOP(BYTE bCmd);
|
|
void DoSendLoginOK();
|
|
void DoSendLoginError();
|
|
void DoSendLoginError(WORD wErrFMT);
|
|
BOOL DoSend(const CPacket& Packet);
|
|
BOOL DoSendX(BYTE bCmd, const void* pData, int nLen);
|
|
BOOL __cdecl DoSendX(const char* pcszFormat, ...);
|
|
BOOL DoSendText(BYTE bCmd, const char* pcsz);
|
|
BOOL DoSendText(const char* pcszID, const char* pcsz, WORD wTX = TX_NORMAL);
|
|
BOOL __cdecl DoSendFmt(WORD wFmt, const char* pcszParamType = NULL, ...);
|
|
BOOL vDoSendFmt(WORD wFmt, const char* pcszParamType, va_list ap);
|
|
public:
|
|
virtual CSOC* IsSOC() const { return (CSOC*)this; }
|
|
virtual BOOL CheckProc(DWORD dwParam) { return TRUE; }
|
|
virtual DWORD GetSendTimeOut() const { return 5 * 1000; }
|
|
virtual BOOL IsListenSocket() const { return FALSE; }
|
|
virtual BOOL IsClientSocket() const { return FALSE; }
|
|
virtual BOOL IsServerSocket() const { return FALSE; }
|
|
virtual UINT GetType() const { return 0; }
|
|
virtual UINT GetType3() const = 0;
|
|
virtual const CTEXTFmtArray& GetTEXTFmtArray();
|
|
virtual const CTEXTFmt& GetTEXTFmt(WORD wFmt);
|
|
virtual BOOL DoProcessPacket();
|
|
virtual void OnOpen();
|
|
virtual BOOL OnSetupSocket();
|
|
virtual void OnAddSocket();
|
|
virtual void OnDropping();
|
|
virtual void OnDelSocket();
|
|
virtual void OnShutdown();
|
|
virtual void OnClose();
|
|
virtual void OnDelete();
|
|
virtual void OnSendKeepAlive();
|
|
#if !defined(USE_OVRIO)
|
|
virtual BOOL OnOverflow(int nSizeReq, int nRetry, DWORD dwTimeBegin);
|
|
#endif // !defined(USE_OVRIO)
|
|
public: // packet handler map
|
|
void OnIgnore();
|
|
void OnKeepAlive();
|
|
#ifdef USE_OVRIO
|
|
COVRIO* newCOVRIO(const BYTE* pb, int nSize);
|
|
void deleteCOVRIO(COVRIO* pOVRIO);
|
|
void OnOVRIO_Completion(DWORD dwError, DWORD cbTransferred, COVRIO* pOVRIO, DWORD dwFlags);
|
|
#endif // USE_OVRIO
|
|
int aSnd_GetDataSize();
|
|
protected:
|
|
BOOL IsSendPossible() const { return !(m_DW.m_xErrSEND || m_DW.m_xAbortyRemote || m_DW.m_xGracefulLocal); }
|
|
BOOL IsReceivePossible() const { return !(m_DW.m_xErrRECEIVE || m_DW.m_xAbortyRemote || m_DW.m_xGracefulRemote); }
|
|
BOOL DoClose();
|
|
void CheckAutoDelete();
|
|
void SetDroppingTicks();
|
|
BOOL CreateAndAttach();
|
|
void CallOnOpen(SOCKET soc);
|
|
void CallOnDropping();
|
|
void CallOnShutdown(int nHow);
|
|
void CallOnClose();
|
|
void CallOnDelete();
|
|
protected:
|
|
void DoPacketProcessing();
|
|
BOOL OnReceive();
|
|
int DoReceive(BYTE* pbBuf, int nLen);
|
|
int OnSend();
|
|
protected:
|
|
void SendKeepAlive();
|
|
void ResetKeepAliveAll();
|
|
void ResetKeepAliveRcv();
|
|
void ResetKeepAliveSnd();
|
|
protected:
|
|
EException GetExceptionCode(int nErrorCode);
|
|
EException DoErrorReport(int nErrorCode, BOOL bDropIfErrorOccur = FALSE);
|
|
EException DoExceptions(EException eException, BOOL bDropIfErrorOccur = FALSE);
|
|
};
|
|
|
|
class CSOCListen : public CSOC
|
|
{
|
|
friend class CSOC;
|
|
friend class CSOCManager;
|
|
protected:
|
|
PFN_CreateSOCClient m_pfnCSC;
|
|
DWORD m_dwCSCParam1;
|
|
DWORD m_dwCSCParam2;
|
|
DWORD m_dwListenTime;
|
|
DWORD m_dwLastCheck;
|
|
public:
|
|
CSOCListen(int nPort = 0, DWORD dwListenTime = 250);
|
|
virtual ~CSOCListen();
|
|
DWORD GetListenTime() const { return m_dwListenTime; }
|
|
void SetListenTime(DWORD dwListenTime) { m_dwListenTime = dwListenTime; }
|
|
BOOL GetAllowAccept() const { return m_DW.m_xAllowAccept; }
|
|
void SetAllowAccept(BOOL bAllowAccept) { m_DW.m_xAllowAccept = !!bAllowAccept; }
|
|
void GetCSCParam(PFN_CreateSOCClient& pfnCSC, DWORD& dwCSCParam1, DWORD& dwCSCParam2) const;
|
|
void SetCSCParam(PFN_CreateSOCClient pfnCSC, DWORD dwCSCParam1, DWORD dwCSCParam2);
|
|
public:
|
|
virtual BOOL IsListenSocket() const { return TRUE; }
|
|
virtual UINT GetType3() const { return SOCNEXT_EXCLISTEN; }
|
|
virtual BOOL BindAndListenSocket();
|
|
virtual void OnAcception();
|
|
virtual CSOCClient* OnNewClientSocket() const;
|
|
virtual BOOL OnAddrAcceptionCheck(const sockaddr_in& Addr) { return TRUE; }
|
|
virtual BOOL DoProcessPacket() { m_aRcv.FreeAll(); return FALSE; }
|
|
};
|
|
|
|
class CSOCConnect : public CSOC
|
|
{
|
|
friend class CSOC;
|
|
friend class CSOCManager;
|
|
DECLARE_PACKET_MAP(CSOCConnect)
|
|
protected:
|
|
time_t m_tConnection;
|
|
DWORD m_dwLingerTime;
|
|
CFileTransfer* m_pFTPStart;
|
|
public:
|
|
CSOCConnect(DWORD dwLingerTime);
|
|
virtual ~CSOCConnect();
|
|
public:
|
|
time_t GetConnectionTime() const { return m_tConnection; }
|
|
DWORD GetConnectionTicks() const;
|
|
DWORD GetConnectionTimeString(CStr& strTime, BOOL bForceShowMin = FALSE, BOOL bForceShowHour = FALSE) const;
|
|
void SetConnectionTime();
|
|
DWORD GetLingerTime() const { return m_dwLingerTime; }
|
|
void SetLingerTime(DWORD dwLingerTime) { m_dwLingerTime = dwLingerTime; }
|
|
public:
|
|
BOOL DoFileTransfer(DWORD dwGUARD, const char* pcszFileNameRemote);
|
|
CFileTransfer* FindFTP(DWORD dwFTID) const;
|
|
CFileTransfer* FindFTP(const char* pcszFileNameRemote) const;
|
|
void DoFTPCloseAllAsError();
|
|
public:
|
|
virtual void DoTextDisplay(const char* pcszID, const char* pcszMsg, WORD wTX);
|
|
public: // FTP virtual...
|
|
virtual void OnFTPFileInfoNotify(CFileTransfer* pFTP);
|
|
virtual void OnFTPError(CFileTransfer* pFTP, long lErrorCode);
|
|
virtual const char* OnFTPDirectory(BOOL bClientSite) const;
|
|
virtual const char* OnFTPFileNameValidation(const char* pcszFileName) const;
|
|
virtual void OnFTPFileMap(DWORD dwGUARD, const char* pcszFileNameRemote, CStr& strFileNameLocal, BOOL bClientSite) const;
|
|
virtual void OnFTPSrvrError(DWORD dwGUARD, const char* pcszFileNameRemote, DWORD dwError);
|
|
virtual void OnFTPNotFound(DWORD dwFTID, BOOL bClientSite);
|
|
virtual CFileTransfer* OnAllocFileTransfer(DWORD dwGUARD, const char* pcszFileNameRemote, DWORD& dwError);
|
|
virtual CFileTransfer* OnAllocFileTransfer(DWORD dwFTID, DWORD dwGUARD, const char* pcszFileNameRemote, DWORD dwTime, long lSize, DWORD& dwError);
|
|
virtual CFileTransfer* OnNewFileTransfer(DWORD dwFTID, DWORD dwGUARD, const char* pcszFileNameRemote, const char* pcszFileNameLocal);
|
|
virtual void OnFreeFileTransfer(CFileTransfer* pFTP);
|
|
virtual void OnFTPRead(CFileTransfer* pFTP, long lSize);
|
|
virtual void OnFTPWrite(CFileTransfer* pFTP, long lPosition);
|
|
virtual void OnFTPTerminate(CFileTransfer* pFTP);
|
|
virtual BOOL DoFTPWrite(CFileTransfer* pFTP, const BYTE* pb, long lSize);
|
|
virtual long DoFTPRead(CFileTransfer* pFTP, const BYTE* pb, long lSize);
|
|
public: // packet handler map
|
|
void OnText();
|
|
void OnTextFmt();
|
|
void OnFTP();
|
|
protected:
|
|
BOOL CheckDroppingTicks(DWORD dwTicks);
|
|
};
|
|
|
|
class CSOCClient : public CSOCConnect
|
|
{
|
|
friend class CSOC;
|
|
friend class CSOCListen;
|
|
friend class CSOCConnect;
|
|
friend class CSOCServer;
|
|
friend class CSOCManager;
|
|
DECLARE_PACKET_MAP(CSOCClient)
|
|
public:
|
|
TARRAYREF(CStr) m_astrGroups;
|
|
public:
|
|
CSOCClient(DWORD dwLingerTime = MY_LINGER_TIME);
|
|
virtual ~CSOCClient();
|
|
public:
|
|
virtual BOOL IsClientSocket() const { return TRUE; }
|
|
virtual UINT GetType3() const { return SOCNEXT_EXCCLIENT; }
|
|
virtual BOOL OnCheckIDAndPassword(const char* pcszID, const char* pcszPW);
|
|
virtual void OnAccept();
|
|
public: // packet handler map
|
|
protected:
|
|
void CallOnAccept();
|
|
};
|
|
|
|
class CSOCServer : public CSOCConnect
|
|
{
|
|
friend class CSOC;
|
|
friend class CSOCListen;
|
|
friend class CSOCConnect;
|
|
friend class CSOCClient;
|
|
friend class CSOCManager;
|
|
DECLARE_PACKET_MAP(CSOCServer)
|
|
public:
|
|
CSOCServer(const char* pcszTarget = NULL, int nPort = 0, DWORD dwLingerTime = MY_LINGER_TIME);
|
|
virtual ~CSOCServer();
|
|
public:
|
|
void CallOnConnectionTimeOut(); // do not use the function, should be protected but...
|
|
public:
|
|
virtual BOOL IsServerSocket() const { return TRUE; }
|
|
virtual UINT GetType3() const { return SOCNEXT_EXCSERVER; }
|
|
virtual void OnConnect();
|
|
virtual void OnConnectionTimeOut();
|
|
public: // packet handler map
|
|
protected:
|
|
BOOL DoConnect();
|
|
void CallOnConnect();
|
|
};
|
|
|
|
class CSOCUDP
|
|
{
|
|
protected:
|
|
CSockAddr m_Addr;
|
|
SOCKET m_hSocket;
|
|
int m_nPort;
|
|
public:
|
|
CSOCUDP(int nPort = 0);
|
|
virtual ~CSOCUDP();
|
|
CSockAddr& GetSockAddr() const { return *(CSockAddr*)&m_Addr; }
|
|
operator SOCKET () const { return m_hSocket; }
|
|
SOCKET GetSocket() const { return m_hSocket; }
|
|
BOOL IsValidSafe() const { return this && (m_hSocket != INVALID_SOCKET); }
|
|
BOOL IsValid() const { return m_hSocket != INVALID_SOCKET; }
|
|
int GetPort() const { return m_nPort; }
|
|
UINT GetMAX_MSG_SIZE() const;
|
|
BOOL CreateAndBind(int nPort = 0);
|
|
void Drop();
|
|
BOOL IsReadable() const;
|
|
BOOL IsWritable() const;
|
|
int Send(const void* pBuffer, int nLen, DWORD dwAddr, int nPort);
|
|
int Recv(void* pBuffer, int nLen, DWORD& dwAddr, int& nPort);
|
|
int Send(const void* pBuffer, int nLen, const sockaddr_in& Addr);
|
|
int Recv(void* pBuffer, int nLen, sockaddr_in& Addr);
|
|
};
|
|
|
|
template <class CSOCClass>
|
|
class TSOCArray : public TARRAY(CSOCClass*)
|
|
{
|
|
public:
|
|
public:
|
|
int FindIndex(CSOCClass* pSOC) const
|
|
{
|
|
int nSize = GetSize();
|
|
CSOCClass** pp = &GetAt(nSize);
|
|
|
|
while(nSize-- > 0) {
|
|
if (*--pp == pSOC)
|
|
break;
|
|
}
|
|
|
|
return nSize;
|
|
}
|
|
int DelIfExist(CSOCClass* pSOC)
|
|
{
|
|
int nIndex = FindIndex(pSOC);
|
|
|
|
if (nIndex != -1) {
|
|
Del(nIndex);
|
|
}
|
|
|
|
return nIndex;
|
|
}
|
|
};
|
|
|
|
#ifdef WIN32
|
|
#define XFD_ARRAY fd_set
|
|
#else // !WIN32
|
|
struct XFD_ARRAY
|
|
{
|
|
public:
|
|
int fd_count;
|
|
SOCKET fd_array[FD_SETSIZE];
|
|
};
|
|
#endif // WIN32
|
|
|
|
class XFD_SET : protected XFD_ARRAY
|
|
{
|
|
private:
|
|
#if !defined(WIN32)
|
|
fd_set m_FD_SET;
|
|
#endif // !defined(WIN32)
|
|
public:
|
|
XFD_SET();
|
|
XFD_SET(SOCKET soc);
|
|
XFD_SET(const XFD_SET& that);
|
|
int GetCount() const { return fd_count; }
|
|
SOCKET* GetFDs() const { return (SOCKET*)&fd_array[0]; }
|
|
void Assign(const XFD_SET& that);
|
|
int FindIndexFromHandle(SOCKET soc) const;
|
|
void ZERO();
|
|
BOOL ISSET(SOCKET soc);
|
|
void SET(SOCKET soc);
|
|
void CLR(SOCKET soc);
|
|
void CLR_Index(int nIndex);
|
|
XFD_ARRAY& GetFD_ARRAY() const;
|
|
fd_set& GetFD_SET() const;
|
|
int Select(int nType);
|
|
#ifdef _DEBUG
|
|
void CheckHandleMap() const;
|
|
#endif // _DEBUG
|
|
};
|
|
|
|
class CFDSet : protected XFD_SET
|
|
{
|
|
protected:
|
|
PSOC m_paSOCs[FD_SETSIZE];
|
|
public:
|
|
CFDSet();
|
|
virtual ~CFDSet();
|
|
public:
|
|
CSOC* GetSOCFromHandle(SOCKET soc) const;
|
|
int GetCount() const { return fd_count; }
|
|
PSOC* GetStartOfSOCs() const { return (PSOC*)&m_paSOCs[0]; }
|
|
PSOC FindSOC(SOCKET soc, int& nIndex) const;
|
|
#ifdef _DEBUG
|
|
void CheckHandleMap() const;
|
|
#endif // _DEBUG
|
|
void SET(const CSOC& SOC);
|
|
void CLR(const CSOC& SOC);
|
|
void CLR_Index(int nIndex);
|
|
protected:
|
|
BOOL AddSOC(CSOC& SOC);
|
|
void DelSOC(CSOC& SOC);
|
|
void DelSOCFromIndex(CSOC& SOC, int nIndex);
|
|
};
|
|
|
|
class CDroppings : protected TSOCArray<CSOC>
|
|
{
|
|
friend class CSOCManager;
|
|
public:
|
|
public:
|
|
void AddWithFlush(CSOC* pSOC);
|
|
};
|
|
|
|
template <int nFDArrayMAX>
|
|
class TFD_SET_Dynamic
|
|
{
|
|
private:
|
|
int m_nLevel;
|
|
XFD_SET* m_pFD_SET;
|
|
XFD_SET m_aFD_SET[nFDArrayMAX];
|
|
TARRAYPTR2(XFD_SET*) m_paFD_SET;
|
|
public:
|
|
TFD_SET_Dynamic()
|
|
{
|
|
m_nLevel = 0;
|
|
m_pFD_SET = NULL;
|
|
m_paFD_SET.SetGrowBy(3);
|
|
}
|
|
~TFD_SET_Dynamic()
|
|
{
|
|
ASSERT(m_nLevel == 0);
|
|
}
|
|
void Alloc()
|
|
{
|
|
if (m_nLevel < nFDArrayMAX) {
|
|
m_pFD_SET = &m_aFD_SET[m_nLevel];
|
|
} else {
|
|
XFD_SET* p = (XFD_SET*)malloc(sizeof(XFD_SET));
|
|
m_paFD_SET.Add() = p;
|
|
m_pFD_SET = p;
|
|
}
|
|
m_nLevel++;
|
|
}
|
|
void Free()
|
|
{
|
|
ASSERT(m_nLevel > 0);
|
|
#ifdef _DEBUG
|
|
if (m_nLevel <= nFDArrayMAX) {
|
|
ASSERT(m_paFD_SET.GetSize() == 0);
|
|
} else {
|
|
ASSERT(nFDArrayMAX + m_paFD_SET.GetSize() == m_nLevel);
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
if (--m_nLevel > 0) {
|
|
if (m_nLevel < nFDArrayMAX) {
|
|
m_pFD_SET = &m_aFD_SET[m_nLevel];
|
|
} else {
|
|
int nIndex = m_nLevel - nFDArrayMAX;
|
|
m_paFD_SET.Del(nIndex);
|
|
if (--nIndex < 0) {
|
|
m_pFD_SET = &m_aFD_SET[nFDArrayMAX - 1];
|
|
} else {
|
|
m_pFD_SET = m_paFD_SET.At(nIndex);
|
|
}
|
|
}
|
|
} else {
|
|
ASSERT(m_nLevel == 0);
|
|
m_pFD_SET = NULL;
|
|
}
|
|
}
|
|
XFD_SET* GetFD_SET(const TSOCArray<CSOC>& aSOCs) const
|
|
{
|
|
ASSERT(m_pFD_SET && &aSOCs);
|
|
|
|
int nSize = aSOCs.GetSize();
|
|
XFD_SET& fd = *m_pFD_SET;
|
|
XFD_ARRAY& fda = fd.GetFD_ARRAY();
|
|
fda.fd_count = nSize;
|
|
#if !defined(WIN32)
|
|
fd_set& u = fd.GetFD_SET();
|
|
FD_ZERO(&u);
|
|
#endif // !defined(WIN32)
|
|
SOCKET* pSOCKET = &fda.fd_array[0];
|
|
CSOC** ppSOC = &aSOCs.GetAt(0);
|
|
while(nSize-- > 0) {
|
|
CSOC* pSOC = *ppSOC++;
|
|
*pSOCKET++ = *pSOC;
|
|
#if !defined(WIN32)
|
|
SOCKET soc = *pSOC;
|
|
FD_SET(soc, &u);
|
|
#endif // !defined(WIN32)
|
|
}
|
|
|
|
return &fd;
|
|
}
|
|
XFD_SET* GetFD_SET(const XFD_SET& fd) const
|
|
{
|
|
ASSERT(m_pFD_SET && &fd);
|
|
|
|
m_pFD_SET->Assign(fd);
|
|
|
|
return m_pFD_SET;
|
|
}
|
|
};
|
|
|
|
class CSOCManager : public CFDSet
|
|
{
|
|
friend class CSOC;
|
|
friend class CSOCListen;
|
|
friend class CSOCConnect;
|
|
friend class CSOCClient;
|
|
friend class CSOCServer;
|
|
private:
|
|
TFD_SET_Dynamic<STATIC_FDARRAY_MAX> m_FD_Dynamic;
|
|
protected:
|
|
int m_nStarted;
|
|
// socsystem
|
|
WORD m_wVersionRequested;
|
|
#ifdef WIN32
|
|
WSADATA m_wsaData;
|
|
#endif // WIN32
|
|
// socmanager
|
|
int m_nDroppingSockets;
|
|
TSOCArray<CSOC> m_paConnectings;
|
|
CDroppings m_paDroppings;
|
|
public:
|
|
DWORD m_dwConnectTimeOut;
|
|
CTimerPool m_aTimerPool;
|
|
public:
|
|
CSOCManager(DWORD dwConnectTimeOut = 20000);
|
|
virtual ~CSOCManager();
|
|
public:
|
|
BOOL IsStarted() const { return m_nStarted > 0; }
|
|
DWORD GetConnectTimeOut() const { return m_dwConnectTimeOut; }
|
|
void SetConnectTimeOut(DWORD dwConnectTimeOut) { m_dwConnectTimeOut = dwConnectTimeOut; }
|
|
public:
|
|
CSOCListen* GetListenSocket() const;
|
|
CSOC* FindSOC(int nID = CSOC_SERVER_ID) const;
|
|
CSOCServer* FindSOCServeLogin(int nID = CSOC_SERVER_ID) const;
|
|
CSOC* GetNextSocket(UINT uType, UINT uMask, CSOC* pSOC, int& nIndex, DWORD dwParam = 0);
|
|
BOOL DoListen(CSOCListen* pSOCListen, int nPort = 0);
|
|
CSOCListen* DoListen(int nPort, PFN_CreateSOCClient pfnCSC, DWORD dwCSCParam1, DWORD dwCSCParam2);
|
|
BOOL DoConnect(CSOCServer* pSOCServer, const char* pcszTarget = NULL, int nPort = 0);
|
|
void DropAll(BOOL bWait = TRUE);
|
|
EException OnExceptions(CSOC* pSOC, EException eException, BOOL bDropIfErrorOccur = FALSE);
|
|
public:
|
|
virtual BOOL Init();
|
|
virtual void Exit();
|
|
virtual BOOL Startup();
|
|
virtual void Shutdown();
|
|
virtual BOOL SetupInitialOption();
|
|
virtual BOOL InitSignal();
|
|
virtual void ExitSignal();
|
|
virtual void OnAddSocket(CSOC& SOC);
|
|
virtual void OnDelSocket(CSOC& SOC);
|
|
virtual void SingleStep();
|
|
virtual CSOCClient* OnNewClientSocket(const CSOCListen& SOCListen, DWORD dwCSCParam1, DWORD dwCSCParam2) const;
|
|
protected:
|
|
BOOL AddSocket(CSOC& SOC);
|
|
void CallOnAddSocket(CSOC& SOC);
|
|
void CallOnDelSocket(CSOC& SOC);
|
|
void OnDrop(CSOC* pSOC);
|
|
void DoConnecting(CSOCServer* pSOCServer, BOOL bConnecting);
|
|
BOOL IsSafeToShutdown() const;
|
|
protected: // in single step
|
|
void CheckDropping();
|
|
void CheckFlush();
|
|
void CheckReading();
|
|
protected:
|
|
EException DoErrorReport(CSOC* pSOC, int nErrorCode, BOOL bDropIfErrorOccur = FALSE);
|
|
};
|
|
|
|
#endif // !defined(__MUGSOCS__)
|