ilk commit

This commit is contained in:
2025-08-19 15:55:41 +03:00
parent 385548afa6
commit bcbb5db79f
629 changed files with 141341 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
#pragma once
template <typename T>
class Atomic
{
public:
Atomic() {}
Atomic(T value) : m_atomic(value) {}
operator T() { return (T) m_atomic; }
INLINE Atomic<T>& operator++() { increment(); return *this; }
INLINE Atomic<T>& operator--() { decrement(); return *this; }
// NOTE: The following operators should only be used if it can't be helped.
#define ATOMIC_COMPARISON(op) \
template <typename T2> \
INLINE friend bool operator op (Atomic<T>& lhs, const T2 rhs) { return lhs.m_atomic op rhs; }
// Hide signed/unsigned comparison warning.
// It's only valid on VS2010, when the type is always long (so, signed).
#pragma warning(push)
#pragma warning(disable: 4018)
ATOMIC_COMPARISON(>)
ATOMIC_COMPARISON(>=)
ATOMIC_COMPARISON(<)
ATOMIC_COMPARISON(<=)
ATOMIC_COMPARISON(==)
ATOMIC_COMPARISON(!=)
#pragma warning(pop)
#undef ATOMIC_COMPARISON
template <typename T2> INLINE Atomic<T>& operator=(const T2& rhs) { m_atomic = rhs; return *this; }
template <typename T2> INLINE Atomic<T>& operator+=(const T2 rhs) { m_atomic += rhs; return *this; }
template <typename T2> INLINE Atomic<T>& operator-=(const T2 rhs) { m_atomic -= rhs; return *this; }
INLINE T increment() { return ++m_atomic; }
INLINE T decrement() { return --m_atomic; }
INLINE bool compare_exchange(T & expected, T desired) { return m_atomic.compare_exchange_strong(expected, desired); }
protected:
std::atomic<T> m_atomic;
private:
Atomic(const Atomic & other); /* disable copy constructor */
};
+175
View File
@@ -0,0 +1,175 @@
#pragma once
#include <vector>
class ByteBuffer
{
public:
const static size_t DEFAULT_SIZE = 32;
bool m_doubleByte;
ByteBuffer(): _rpos(0), _wpos(0), m_doubleByte(true) { _storage.reserve(DEFAULT_SIZE); }
ByteBuffer(size_t res): _rpos(0), _wpos(0), m_doubleByte(true) { _storage.reserve(res <= 0 ? DEFAULT_SIZE : res); }
ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { }
virtual ~ByteBuffer() {}
void clear()
{
_storage.clear();
_rpos = _wpos = 0;
}
template <typename T> void append(T value) { append((uint8 *)&value, sizeof(value)); }
template <typename T> void put(size_t pos,T value) { put(pos,(uint8 *)&value, sizeof(value)); }
// stream like operators for storing data
ByteBuffer &operator<<(bool value) { append<char>((char)value); return *this; }
// unsigned
ByteBuffer &operator<<(uint8 value) { append<uint8> (value); return *this; }
ByteBuffer &operator<<(uint16 value) { append<uint16>(value); return *this; }
ByteBuffer &operator<<(uint32 value) { append<uint32>(value); return *this; }
ByteBuffer &operator<<(uint64 value) { append<uint64>(value); return *this; }
// signed as in 2e complement
ByteBuffer &operator<<(int8 value) { append<int8> (value); return *this; }
ByteBuffer &operator<<(int16 value) { append<int16>(value); return *this; }
ByteBuffer &operator<<(int32 value) { append<int32>(value); return *this; }
ByteBuffer &operator<<(int64 value) { append<int64>(value); return *this; }
ByteBuffer &operator<<(float value) { append<float>(value); return *this; }
ByteBuffer &operator<<(ByteBuffer &value)
{
if (value.wpos())
append(value.contents(), value.wpos());
return *this;
}
// stream like operators for reading data
ByteBuffer &operator>>(bool &value) { value = read<char>() > 0 ? true : false; return *this; }
// unsigned
ByteBuffer &operator>>(uint8 &value) { value = read<uint8>(); return *this; }
ByteBuffer &operator>>(uint16 &value) { value = read<uint16>(); return *this; }
ByteBuffer &operator>>(uint32 &value) { value = read<uint32>(); return *this; }
ByteBuffer &operator>>(uint64 &value) { value = read<uint64>(); return *this; }
// signed as in 2e complement
ByteBuffer &operator>>(int8 &value) { value = read<int8>(); return *this; }
ByteBuffer &operator>>(int16 &value) { value = read<int16>(); return *this; }
ByteBuffer &operator>>(int32 &value) { value = read<int32>(); return *this; }
ByteBuffer &operator>>(int64 &value) { value = read<int64>(); return *this; }
ByteBuffer &operator>>(float &value) { value = read<float>(); return *this; }
// Hacky KO string flag - either it's a single byte length, or a double byte.
void SByte() { m_doubleByte = false; }
void DByte() { m_doubleByte = true; }
ByteBuffer &operator<<(const std::string &value) { *this << value.c_str(); return *this; }
ByteBuffer &operator<<(std::string &value) { *this << value.c_str(); return *this; }
ByteBuffer &operator<<(const char *str)
{
uint16 len = (uint16)strlen(str);
if (m_doubleByte)
append((uint8*)&len, 2);
else
append((uint8*)&len, 1);
append((uint8 *)str, len);
return *this;
}
ByteBuffer &operator<<(char *str) { *this << (const char*)str; return *this; }
ByteBuffer &operator>>(std::string& value)
{
uint16 len;
value.clear();
if (m_doubleByte)
len = read<uint16>();
else
len = read<uint8>();
if (_rpos + len <= size())
{
for (uint16 i = 0; i < len; i++)
value.push_back(read<char>());
}
return *this;
}
uint8 operator[](size_t pos) { return read<uint8>(pos); }
INLINE size_t rpos() { return _rpos; };
INLINE size_t rpos(size_t rpos) { return _rpos = rpos; };
INLINE size_t wpos() { return _wpos; };
INLINE size_t wpos(size_t wpos) { return _wpos = wpos; };
template <typename T> T read()
{
T r = read<T>(_rpos);
_rpos += sizeof(T);
return r;
};
template <typename T> T read(size_t pos) const
{
//ASSERT(pos + sizeof(T) <= size());
if (pos + sizeof(T) > size())
return (T)0;
return *((T*)&_storage[pos]);
};
void read(void *dest, size_t len)
{
if (_rpos + len <= size())
memcpy(dest, &_storage[_rpos], len);
else // throw error();
memset(dest, 0, len);
_rpos += len;
};
const uint8 *contents() const { return &_storage[0]; };
INLINE size_t size() const { return _storage.size(); };
// one should never use resize
void resize(size_t newsize)
{
_storage.resize(newsize);
_rpos = 0;
_wpos = size();
};
void reserve(size_t ressize) { if (ressize > size()) _storage.reserve(ressize); };
// append to the end of buffer
void append(const std::string& str) { append((uint8 *)str.c_str(),str.size() + 1); }
void append(const char *src, size_t cnt) { return append((const uint8 *)src, cnt); }
void append(const void *src, size_t cnt)
{
if (!cnt)
return;
// 10MB is far more than you'll ever need.
ASSERT(size() < 10000000);
if (_storage.size() < _wpos + cnt)
_storage.resize(_wpos + cnt);
memcpy(&_storage[_wpos], src, cnt);
_wpos += cnt;
}
void append(const ByteBuffer& buffer) { if (buffer.size() > 0) append(buffer.contents(), buffer.size()); }
void append(const ByteBuffer& buffer, size_t len)
{
ASSERT(buffer._rpos + len <= buffer.size());
append(buffer.contents() + buffer._rpos, len);
}
void put(size_t pos, const void *src, size_t cnt)
{
ASSERT(pos + cnt <= size());
memcpy(&_storage[pos], src, cnt);
}
protected:
// read and write positions
size_t _rpos, _wpos;
std::vector<uint8> _storage;
};
+258
View File
@@ -0,0 +1,258 @@
#include "stdafx.h"
#include "CircularBuffer.h"
/** Constructor
*/
CircularBuffer::CircularBuffer()
{
m_buffer = m_bufferEnd = m_regionAPointer = m_regionBPointer = nullptr;
m_regionASize = m_regionBSize = 0;
}
/** Destructor
*/
CircularBuffer::~CircularBuffer()
{
free(m_buffer);
}
/** Read bytes from the buffer
* @param destination pointer to destination where bytes will be written
* @param bytes number of bytes to read
* @return true if there was enough data, false otherwise
*/
bool CircularBuffer::Read(void * destination, size_t bytes)
{
// copy as much out of region a
size_t cnt = bytes;
size_t aRead = 0, bRead = 0;
if( (m_regionASize + m_regionBSize) < bytes )
return false;
// If we have both region A and region B, always "finish" off region A first, as
// this will contain the "oldest" data
if( m_regionASize > 0 )
{
aRead = (cnt > m_regionASize) ? m_regionASize : cnt;
memcpy(destination, m_regionAPointer, aRead);
m_regionASize -= aRead;
m_regionAPointer += aRead;
cnt -= aRead;
}
// Data left over? read the data from buffer B
if( cnt > 0 && m_regionBSize > 0 )
{
bRead = (cnt > m_regionBSize) ? m_regionBSize : cnt;
memcpy((char*)destination + aRead, m_regionBPointer, bRead);
m_regionBSize -= bRead;
m_regionBPointer += bRead;
cnt -= bRead;
}
// is buffer A empty? move buffer B to buffer A, to increase future performance
if( m_regionASize == 0 )
{
if( m_regionBSize > 0 )
{
// push it all to the start of the buffer.
if( m_regionBPointer != m_buffer )
memmove(m_buffer, m_regionBPointer, m_regionBSize);
m_regionAPointer = m_buffer;
m_regionASize = m_regionBSize;
m_regionBPointer = nullptr;
m_regionBSize = 0;
}
else
{
// no data in region b
m_regionBPointer = nullptr;
m_regionBSize = 0;
m_regionAPointer = m_buffer;
m_regionASize = 0;
}
}
return true;
}
void CircularBuffer::AllocateB()
{
//printf("[allocating B]\n");
m_regionBPointer = m_buffer;
}
/** Write bytes to the buffer
* @param data pointer to the data to be written
* @param bytes number of bytes to be written
* @return true if was successful, otherwise false
*/
bool CircularBuffer::Write(const void * data, size_t bytes)
{
// If buffer B exists, write to it.
if( m_regionBPointer != nullptr )
{
if( GetBFreeSpace() < bytes )
return false;
memcpy(&m_regionBPointer[m_regionBSize], data, bytes);
m_regionBSize += bytes;
return true;
}
// Otherwise, write to buffer A, or initialize buffer B depending on which has more space.
if( GetAFreeSpace() < GetSpaceBeforeA() )
{
AllocateB();
if( GetBFreeSpace() < bytes )
return false;
memcpy(&m_regionBPointer[m_regionBSize], data, bytes);
m_regionBSize += bytes;
return true;
}
else
{
if( GetAFreeSpace() < bytes )
return false;
memcpy(&m_regionAPointer[m_regionASize], data, bytes);
m_regionASize += bytes;
return true;
}
}
/** Returns the number of available bytes left.
*/
size_t CircularBuffer::GetSpace()
{
if( m_regionBPointer != nullptr )
return GetBFreeSpace();
else
{
// would allocating buffer B get us more data?
if( GetAFreeSpace() < GetSpaceBeforeA() )
{
AllocateB();
return GetBFreeSpace();
}
// or not?
return GetAFreeSpace();
}
}
/** Returns the number of bytes currently stored in the buffer.
*/
size_t CircularBuffer::GetSize()
{
return m_regionASize + m_regionBSize;
}
/** Returns the number of contiguous bytes (that can be pushed out in one operation)
*/
size_t CircularBuffer::GetContiguousBytes()
{
if( m_regionASize ) // A before B
return m_regionASize;
else
return m_regionBSize;
}
/** Removes len bytes from the front of the buffer
* @param len the number of bytes to "cut"
*/
void CircularBuffer::Remove(size_t len)
{
// remove from A first before we remove from b
size_t cnt = len;
size_t aRem, bRem;
// If we have both region A and region B, always "finish" off region A first, as
// this will contain the "oldest" data
if( m_regionASize > 0 )
{
aRem = (cnt > m_regionASize) ? m_regionASize : cnt;
m_regionASize -= aRem;
m_regionAPointer += aRem;
cnt -= aRem;
}
// Data left over? cut the data from buffer B
if( cnt > 0 && m_regionBSize > 0 )
{
bRem = (cnt > m_regionBSize) ? m_regionBSize : cnt;
m_regionBSize -= bRem;
m_regionBPointer += bRem;
cnt -= bRem;
}
// is buffer A empty? move buffer B to buffer A, to increase future performance
if( m_regionASize == 0 )
{
if( m_regionBSize > 0 )
{
// push it all to the start of the buffer.
if( m_regionBPointer != m_buffer )
memmove(m_buffer, m_regionBPointer, m_regionBSize);
m_regionAPointer = m_buffer;
m_regionASize = m_regionBSize;
m_regionBPointer = nullptr;
m_regionBSize = 0;
}
else
{
// no data in region b
m_regionBPointer = nullptr;
m_regionBSize = 0;
m_regionAPointer = m_buffer;
m_regionASize = 0;
}
}
}
/** Returns a pointer at the "end" of the buffer, where new data can be written
*/
void * CircularBuffer::GetBuffer()
{
if( m_regionBPointer != nullptr )
return m_regionBPointer + m_regionBSize;
else
return m_regionAPointer + m_regionASize;
}
/** Allocate the buffer with room for size bytes
* @param size the number of bytes to allocate
*/
void CircularBuffer::Allocate(size_t size)
{
m_buffer = (uint8*)malloc(size);
m_bufferEnd = m_buffer + size;
m_regionAPointer = m_buffer; // reset A to the start
m_bufferSize = size;
}
/** Increments the "writen" pointer forward len bytes
* @param len number of bytes to step
*/
void CircularBuffer::IncrementWritten(size_t len) // known as "commit"
{
if( m_regionBPointer != nullptr )
m_regionBSize += len;
else
m_regionASize += len;
}
/** Returns a pointer at the "beginning" of the buffer, where data can be pulled from
*/
void * CircularBuffer::GetBufferStart()
{
if( m_regionASize > 0 )
return m_regionAPointer;
else
return m_regionBPointer;
}
+84
View File
@@ -0,0 +1,84 @@
#pragma once
class CircularBuffer
{
// allocated whole block pointer
uint8 * m_buffer;
uint8 * m_bufferEnd;
// region A pointer, and size
uint8 * m_regionAPointer;
size_t m_regionASize;
// region size
uint8 * m_regionBPointer;
size_t m_regionBSize;
// allocated size
size_t m_bufferSize;
// pointer magic!
INLINE size_t GetAFreeSpace() { return (m_bufferEnd - m_regionAPointer - m_regionASize); }
INLINE size_t GetSpaceBeforeA() { return (m_regionAPointer - m_buffer); }
INLINE size_t GetSpaceAfterA() { return (m_bufferEnd - m_regionAPointer - m_regionASize); }
INLINE size_t GetBFreeSpace() { if(m_regionBPointer == nullptr) { return 0; } return (m_regionAPointer - m_regionBPointer - m_regionBSize); }
public:
CircularBuffer();
~CircularBuffer();
/** Read bytes from the buffer
* @param destination pointer to destination where bytes will be written
* @param bytes number of bytes to read
* @return true if there was enough data, false otherwise
*/
bool Read(void * destination, size_t bytes);
void AllocateB();
/** Write bytes to the buffer
* @param data pointer to the data to be written
* @param bytes number of bytes to be written
* @return true if was successful, otherwise false
*/
bool Write(const void * data, size_t bytes);
/** Returns the allocated size of the buffer.
*/
INLINE size_t GetAllocatedSize() const { return m_bufferSize; }
/** Returns the number of available bytes left.
*/
size_t GetSpace();
/** Returns the number of bytes currently stored in the buffer.
*/
size_t GetSize();
/** Returns the number of contiguous bytes (that can be pushed out in one operation)
*/
size_t GetContiguousBytes();
/** Removes len bytes from the front of the buffer
* @param len the number of bytes to "cut"
*/
void Remove(size_t len);
/** Returns a pointer at the "end" of the buffer, where new data can be written
*/
void * GetBuffer();
/** Allocate the buffer with room for size bytes
* @param size the number of bytes to allocate
*/
void Allocate(size_t size);
/** Increments the "written" pointer forward len bytes
* @param len number of bytes to step
*/
void IncrementWritten(size_t len); // i.e. "commit"
/** Returns a pointer at the "beginning" of the buffer, where data can be pulled from
*/
void * GetBufferStart();
};
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <map>
#include "KOSocketMgr.h"
typedef std::map<uint16, KOSocket *> SessionMap;
template <class T>
class ClientSocketMgr : public KOSocketMgr<T>
{
public:
ClientSocketMgr<T>() {}
virtual Socket *AssignSocket(SOCKET socket) { return nullptr; }
virtual ~ClientSocketMgr() {}
};
+46
View File
@@ -0,0 +1,46 @@
#include "stdafx.h"
#include "Condition.h"
Condition::Condition() : m_nLockCount(0)
{
}
void Condition::BeginSynchronized()
{
m_lock.lock();
++m_nLockCount;
}
void Condition::EndSynchronized()
{
--m_nLockCount;
m_lock.unlock();
}
uint32 Condition::Wait(time_t timeout)
{
std::unique_lock<std::mutex> lock(m_lock);
m_condition.wait_for(lock, std::chrono::milliseconds(timeout));
return 0;
}
uint32 Condition::Wait()
{
std::unique_lock<std::mutex> lock(m_lock);
m_condition.wait(lock);
return 0;
}
void Condition::Signal()
{
m_condition.notify_one();
}
void Condition::Broadcast()
{
m_condition.notify_all();
}
Condition::~Condition()
{
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <condition_variable>
#include <deque>
class Condition
{
public:
Condition();
~Condition();
void BeginSynchronized();
void EndSynchronized();
uint32 Wait(time_t timeout);
uint32 Wait();
void Signal();
void Broadcast();
private:
int m_nLockCount;
std::condition_variable m_condition;
std::mutex m_lock;
};
+106
View File
@@ -0,0 +1,106 @@
#pragma once
#include <ctime>
class DateTime
{
public:
// Uses the current time by default
DateTime()
{
time_t now;
time(&now);
_tm = localtime(&now);
}
// Uses the timestamp specified
DateTime(time_t timestamp)
{
_tm = localtime(&timestamp);
}
// Constructs a date/time using the specified date parts.
DateTime(uint16 sYear, uint8 bMonth, uint8 bDay, uint8 bHour = 0, uint8 bMinute = 0, uint8 bSecond = 0)
{
// Get the current time
time_t now;
time(&now);
_tm = localtime(&now);
// Now update it with the data specified
_tm->tm_year = sYear - 1900;
_tm->tm_mon = bMonth - 1;
_tm->tm_mday = bDay;
_tm->tm_hour = bHour;
_tm->tm_min = bMinute;
_tm->tm_sec = bSecond;
// Finally reconstruct it, so the other data is updated.
Update();
}
// Uses the specified time struct
DateTime(struct tm * _tm)
{
this->_tm = _tm;
}
// Simple getters to retrieve & convert time data to a more conventional form
uint16 GetYear() { return _tm->tm_year + 1900; }
uint8 GetMonth() { return _tm->tm_mon + 1; }
uint8 GetDay() { return _tm->tm_mday; }
uint8 GetDayOfWeek() { return _tm->tm_wday; }
uint8 GetHour() { return _tm->tm_hour; }
uint8 GetMinute() { return _tm->tm_min; }
uint8 GetSecond() { return _tm->tm_sec; }
// NOTE: If any of these overflow, they'll be handled by mktime() accordingly.
// This makes our life *much* easier; date/time logic is not pretty.
void INLINE AddYears(int iYears)
{
_tm->tm_year += iYears;
Update();
}
void INLINE AddMonths(int iMonths)
{
_tm->tm_mon += iMonths;
Update();
}
void INLINE AddWeeks(int iWeeks)
{
AddDays(iWeeks * 7);
}
void INLINE AddDays(int iDays)
{
_tm->tm_mday += iDays;
Update();
}
void INLINE AddHours(int iHours)
{
_tm->tm_hour += iHours;
Update();
}
void INLINE AddMinutes(int iMinutes)
{
_tm->tm_min += iMinutes;
Update();
}
void INLINE AddSeconds(int iSeconds)
{
_tm->tm_sec += iSeconds;
Update();
}
private:
void INLINE Update() { mktime(_tm); }
protected:
struct tm * _tm;
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,67 @@
f:\005server\shared\debug\shared.pdb
f:\005server\shared\debug\shared.ıdb
f:\005server\shared\debug\tstrıng.obj
f:\005server\shared\debug\socketwın32.obj
f:\005server\shared\debug\socketopswın32.obj
f:\005server\shared\debug\socketmgr.obj
f:\005server\shared\debug\socket.obj
f:\005server\shared\debug\jvcryptıon.obj
f:\005server\shared\debug\hardwareınformatıon.obj
f:\005server\shared\debug\shared.pch
f:\005server\shared\debug\stdafx.obj
f:\005server\shared\debug\thread.obj
f:\005server\shared\debug\sıgnal_handler.obj
f:\005server\shared\debug\rwlock.obj
f:\005server\shared\debug\referenceobject.obj
f:\005server\shared\debug\kosocket.obj
f:\005server\shared\debug\globals.obj
f:\005server\shared\debug\odbcrecordset.obj
f:\005server\shared\debug\odbcparameter.obj
f:\005server\shared\debug\odbcconnectıon.obj
f:\005server\shared\debug\odbccommand.obj
f:\005server\shared\debug\condıtıon.obj
f:\005server\shared\debug\cırcularbuffer.obj
f:\005server\shared\debug\lzf.obj
f:\005server\shared\debug\crc32.obj
f:\005server\shared\debug\tımethread.obj
f:\005server\shared\debug\smdfıle.obj
f:\005server\shared\debug\ını.obj
f:\005server\shared\debug\debugutıls.obj
f:\bın\debug\shared.lıb
f:\005server\shared\debug\vcpkg.applocal.log
f:\005server\server source\shared\debug\circularbuffer.obj
f:\005server\server source\shared\debug\condition.obj
f:\005server\server source\shared\debug\crc32.obj
f:\005server\server source\shared\debug\debugutils.obj
f:\005server\server source\shared\debug\globals.obj
f:\005server\server source\shared\debug\hardwareınformation.obj
f:\005server\server source\shared\debug\ıni.obj
f:\005server\server source\shared\debug\jvcryption.obj
f:\005server\server source\shared\debug\kosocket.obj
f:\005server\server source\shared\debug\lzf.obj
f:\005server\server source\shared\debug\odbccommand.obj
f:\005server\server source\shared\debug\odbcconnection.obj
f:\005server\server source\shared\debug\odbcparameter.obj
f:\005server\server source\shared\debug\odbcrecordset.obj
f:\005server\server source\shared\debug\referenceobject.obj
f:\005server\server source\shared\debug\rwlock.obj
f:\005server\server source\shared\debug\signal_handler.obj
f:\005server\server source\shared\debug\smdfile.obj
f:\005server\server source\shared\debug\socket.obj
f:\005server\server source\shared\debug\socketmgr.obj
f:\005server\server source\shared\debug\socketopswin32.obj
f:\005server\server source\shared\debug\socketwin32.obj
f:\005server\server source\shared\debug\stdafx.obj
f:\005server\server source\shared\debug\thread.obj
f:\005server\server source\shared\debug\timethread.obj
f:\005server\server source\shared\debug\tstring.obj
f:\005server\server source\shared\debug\shared.pch
f:\005server\server source\shared\debug\shared.idb
f:\005server\server source\shared\debug\shared.pdb
f:\005server\server source\shared\debug\shared.tlog\cl.command.1.tlog
f:\005server\server source\shared\debug\shared.tlog\cl.read.1.tlog
f:\005server\server source\shared\debug\shared.tlog\cl.write.1.tlog
f:\005server\server source\shared\debug\shared.tlog\lib-link.read.1.tlog
f:\005server\server source\shared\debug\shared.tlog\lib-link.write.1.tlog
f:\005server\server source\shared\debug\shared.tlog\lib.command.1.tlog
f:\005server\server source\shared\debug\shared.tlog\shared.write.1u.tlog
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
stdafx.cpp
CircularBuffer.cpp
Condition.cpp
HardwareInformation.cpp
JvCryption.cpp
KOSocket.cpp
RWLock.cpp
ReferenceObject.cpp
Socket.cpp
SocketMgr.cpp
SocketOpsWin32.cpp
SocketWin32.cpp
Thread.cpp
OdbcCommand.cpp
OdbcConnection.cpp
OdbcParameter.cpp
OdbcRecordset.cpp
globals.cpp
signal_handler.cpp
Generating Code...
F:\005SERVER\server source\shared\database\OdbcCommand.cpp(20,6): warning C4267: 'argument': conversion from 'size_t' to 'SQLUSMALLINT', possible loss of data
DebugUtils.cpp
Ini.cpp
SMDFile.cpp
TimeThread.cpp
Generating Code...
shared.vcxproj -> F:\005SERVER\server source\..\bin\Debug\shared.lib
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
#TargetFrameworkVersion=v4.0:PlatformToolSet=v142:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
Debug|Win32|F:\005SERVER\server source\|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
+25
View File
@@ -0,0 +1,25 @@
#include "stdafx.h"
#include <stdarg.h>
void FormattedDebugString(const char * fmt, ...)
{
char buf[4096], *p = buf;
va_list args;
int n;
va_start(args, fmt);
n = _vsnprintf(p, sizeof(buf) - 3, fmt, args); // allow for proper linefeed & null terminator
va_end(args);
p += (n < 0) ? sizeof buf - 3 : n;
while (p > buf && isspace(p[-1]))
*--p = '\0';
*p++ = '\r';
*p++ = '\n';
*p = '\0';
#ifdef WIN32
OutputDebugString(buf);
#else
printf("%s", buf);
#endif
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void FormattedDebugString(const char * fmt, ...);
+32
View File
@@ -0,0 +1,32 @@
#include "stdafx.h"
#include "HardwareInformation.h"
HardwareInformation::HardwareInformation()
{
}
/**
* @brief License Number Control.
*/
bool HardwareInformation::IsValidHardwareID(std::vector<int64> HardwareIDArray)
{
uint16 MACData1, MACData2 = 0;
GetMacHash(MACData1, MACData2);
int64 nLicenseNumber = GetHardwareID();
foreach (itr, HardwareIDArray)
if (*itr == nLicenseNumber)
return true;
return false;
}
/**
* @brief Get License Number
*/
int64 HardwareInformation::GetHardwareID()
{
uint16 MACData1, MACData2 = 0;
GetMacHash(MACData1, MACData2);
return _atoi64(string_format("%d%d%d%d",MACData1,MACData2,GetCPUHash(),GetVolumeHash()).c_str());
}
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include "stdafx.h"
#include <Iphlpapi.h>
#include <intrin.h>
#pragma comment(lib, "iphlpapi.lib")
class HardwareInformation
{
public:
HardwareInformation();
int64 GetHardwareID();
bool IsValidHardwareID(std::vector<int64> HardwareIDArray);
private:
uint16 HashMacAddress(PIP_ADAPTER_INFO info)
{
uint16 nHash = 0;
for ( uint32 i = 0; i < info->AddressLength; i++ )
nHash += (info->Address[i] << (( i & 1 ) * 8 ));
return nHash;
}
void GetMacHash(uint16 & MACOffset1, uint16 & MACOffset2)
{
IP_ADAPTER_INFO AdapterInfo[32];
DWORD dwBufLen = sizeof( AdapterInfo );
DWORD dwStatus = GetAdaptersInfo( AdapterInfo, &dwBufLen );
if ( dwStatus != ERROR_SUCCESS )
return;
PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
MACOffset1 = HashMacAddress( pAdapterInfo );
if (pAdapterInfo->Next)
MACOffset2 = HashMacAddress( pAdapterInfo->Next );
if (MACOffset1 > MACOffset2)
{
uint16 TempOffset = MACOffset2;
MACOffset2 = MACOffset1;
MACOffset1 = TempOffset;
}
}
uint16 GetCPUHash()
{
int CPUInfo[4] = { 0, 0, 0, 0 };
__cpuid(CPUInfo, 0);
uint16 nHash = 0;
uint16* nPointer = (uint16*)(&CPUInfo[0]);
for (uint16 i = 0; i < 8; i++)
nHash += nPointer[i];
return nHash;
}
uint16 GetVolumeHash()
{
DWORD SerialNum = 0;
GetVolumeInformation( "C:\\", NULL, 0, &SerialNum, NULL, NULL, NULL, 0 );
uint16 nHash = (uint16)(( SerialNum + ( SerialNum >> 16 )) & 0xFFFF );
return nHash;
}
};
+162
View File
@@ -0,0 +1,162 @@
#include "stdafx.h"
#include "Ini.h"
#include <iostream>
#include <fstream>
#include "tstring.h"
#define INI_BUFFER 512
CIni::CIni(const char *lpFilename)
{
m_szFileName = lpFilename;
Load(lpFilename);
}
bool CIni::Load(const char * lpFilename /*= nullptr*/)
{
const char * fn = (lpFilename == nullptr ? m_szFileName.c_str() : lpFilename);
std::ifstream file(fn);
if (!file)
{
printf("Warning: %s does not exist, will use configured defaults.\n", fn);
return false;
}
std::string currentSection;
// If an invalid section is hit
// Ensure that we don't place key/value pairs
// from the invalid section into the previously loaded section.
bool bSkipNextSection = false;
while (!file.eof())
{
std::string line;
getline(file, line);
rtrim(line);
if (line.empty())
continue;
// Check for value strings first
// It's faster than checking for a section
// at the expense of of not being able to use '=' in section names.
// As this is uncommon behaviour, this is a suitable trade-off.
size_t keySeparatorPos = line.find(INI_KEY_SEPARATOR);
if (keySeparatorPos != std::string::npos)
{
if (bSkipNextSection)
continue;
std::string key = line.substr(0, keySeparatorPos),
value = line.substr(keySeparatorPos + 1);
// Clean up key/value to allow for 'key = value'
rtrim(key); /* remove trailing whitespace from keys */
ltrim(value); /* remove preleading whitespace from values */
ConfigMap::iterator itr = m_configMap.find(currentSection);
if (itr == m_configMap.end())
{
m_configMap.insert(std::make_pair(currentSection, ConfigEntryMap()));
itr = m_configMap.find(currentSection);
}
itr->second[key] = value;
continue;
}
// Not a value, so assume it's a section
size_t sectionStart = line.find_first_of(INI_SECTION_START),
sectionEnd = line.find_last_of(INI_SECTION_END);
if (sectionStart == std::string::npos
|| sectionEnd == std::string::npos
|| sectionStart > sectionEnd)
{
/* invalid section */
bSkipNextSection = true;
continue;
}
currentSection = line.substr(sectionStart + 1, sectionEnd - 1);
bSkipNextSection = false;
}
file.close();
return true;
}
void CIni::Save(const char * lpFilename /*= nullptr*/)
{
const char * fn = (lpFilename == nullptr ? m_szFileName.c_str() : lpFilename);
FILE * fp = fopen(fn, "w");
foreach (sectionItr, m_configMap)
{
// Start the section
fprintf(fp, "[%s]" INI_NEWLINE, sectionItr->first.c_str());
// Now list out all the key/value pairs
foreach (keyItr, sectionItr->second)
fprintf(fp, "%s=%s" INI_NEWLINE, keyItr->first.c_str(), keyItr->second.c_str());
// Use a trailing newline to finish the section, to make it easier to read
fprintf(fp, INI_NEWLINE);
}
fclose(fp);
}
int CIni::GetInt(const char* lpAppName, const char* lpKeyName, const int nDefault)
{
ConfigMap::iterator sectionItr = m_configMap.find(lpAppName);
if (sectionItr != m_configMap.end())
{
ConfigEntryMap::iterator keyItr = sectionItr->second.find(lpKeyName);
if (keyItr != sectionItr->second.end())
return atoi(keyItr->second.c_str());
}
SetInt(lpAppName, lpKeyName, nDefault);
return nDefault;
}
bool CIni::GetBool(const char* lpAppName, const char* lpKeyName, const bool bDefault)
{
return GetInt(lpAppName, lpKeyName, bDefault) == 1;
}
void CIni::GetString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, std::string & lpOutString, bool bAllowEmptyStrings /*= true*/)
{
ConfigMap::iterator sectionItr = m_configMap.find(lpAppName);
if (sectionItr != m_configMap.end())
{
ConfigEntryMap::iterator keyItr = sectionItr->second.find(lpKeyName);
if (keyItr != sectionItr->second.end())
{
lpOutString = keyItr->second;
return;
}
}
SetString(lpAppName, lpKeyName, lpDefault);
lpOutString = lpDefault;
}
int CIni::SetInt(const char* lpAppName, const char* lpKeyName, const int nDefault)
{
char tmpDefault[INI_BUFFER];
_snprintf(tmpDefault, INI_BUFFER, "%d", nDefault);
return SetString(lpAppName, lpKeyName, tmpDefault);
}
int CIni::SetString(const char* lpAppName, const char* lpKeyName, const char* lpDefault)
{
ConfigMap::iterator itr = m_configMap.find(lpAppName);
if (itr == m_configMap.end())
{
m_configMap.insert(std::make_pair(lpAppName, ConfigEntryMap()));
itr = m_configMap.find(lpAppName);
}
itr->second[lpKeyName] = lpDefault;
Save();
return 1;
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#define INI_SECTION_START '['
#define INI_SECTION_END ']'
#define INI_KEY_SEPARATOR '='
#define INI_NEWLINE "\n"
class CIni
{
private:
std::string m_szFileName;
// Defines key/value pairs within sections
typedef std::map<std::string, std::string> ConfigEntryMap;
// Defines the sections containing the key/value pairs
typedef std::map<std::string, ConfigEntryMap> ConfigMap;
ConfigMap m_configMap;
public:
CIni(const char *lpFilename);
bool Load(const char * lpFileName = nullptr);
void Save(const char * lpFileName = nullptr);
int GetInt(const char* lpAppName, const char* lpKeyName, const int nDefault);
bool GetBool(const char* lpAppName, const char* lpKeyName, const bool bDefault);
void GetString(const char* lpAppName, const char* lpKeyName, const char* lpDefault, std::string & lpOutString, bool bAllowEmptyStrings = true);
int SetInt(const char* lpAppName, const char* lpKeyName, const int nDefault);
int SetString(const char* lpAppName, const char* lpKeyName, const char* lpDefault);
};
+51
View File
@@ -0,0 +1,51 @@
#include "stdafx.h"
#include "JvCryption.h"
#include "version.h"
#define g_private_key 0x1207500120128966
//#define g_private_key 0x1507500150128966
void CJvCryption::Init() { m_tkey = m_public_key ^ g_private_key; }
uint64 CJvCryption::GenerateKey()
{
#ifdef USE_CRYPTION
// because of their sucky encryption method, 0 means it effectively won't be encrypted.
// We don't want that happening...
do
{
m_public_key = RandUInt64();
} while (!m_public_key);
#endif
return m_public_key;
}
void CJvCryption::JvEncryptionFast(int len, uint8 *datain, uint8 *dataout)
{
uint8 *pkey, lkey, rsk;
int rkey = 2157;
pkey = (uint8 *)&m_tkey;
lkey = (len * 157) & 0xff;
for (int i = 0; i < len; i++)
{
rsk = (rkey >> 8) & 0xff;
dataout[i] = ((datain[i] ^ rsk) ^ pkey[(i % 8)]) ^ lkey;
rkey *= 2171;
}
}
int CJvCryption::JvDecryptionWithCRC32(int len, uint8 *datain, uint8 *dataout)
{
int result;
JvDecryptionFast(len, datain, dataout);
if (crc32(dataout, len - 4, -1) == *(uint32 *)(len - 4 + dataout))
result = len - 4;
else
result = -1;
return result;
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#define USE_CRYPTION
extern "C"
{
#include "crc32.h"
}
class CJvCryption
{
private:
uint64 m_public_key, m_tkey;
public:
CJvCryption() : m_public_key(0) {}
INLINE uint64 GetPublicKey() { return m_public_key; }
uint64 GenerateKey();
void Init();
void JvEncryptionFast(int len, uint8 *datain, uint8 *dataout);
INLINE void JvDecryptionFast(int len, uint8 *datain, uint8 *dataout) { JvEncryptionFast(len, datain, dataout); };
int JvDecryptionWithCRC32(int len, uint8 *datain, uint8 *dataout);
};
+235
View File
@@ -0,0 +1,235 @@
#include "stdafx.h"
#include "KOSocket.h"
#include "packets.h"
#include "version.h"
KOSocket::KOSocket(uint16 socketID, SocketMgr * mgr, SOCKET fd, uint32 sendBufferSize, uint32 recvBufferSize)
: Socket(fd, sendBufferSize, recvBufferSize),
m_socketID(socketID), m_remaining(0), m_usingCrypto(false),
m_readTries(0), m_sequence(0), m_lastResponse(0)
{
SetSocketMgr(mgr);
}
void KOSocket::OnConnect()
{
if (GetRemoteIP() == "127.0.0.1")
TRACE("Connection received from %s:%d\n", GetRemoteIP().c_str(), GetRemotePort());
m_remaining = 0;
m_usingCrypto = false;
m_readTries = 0;
m_sequence = 0;
m_lastResponse = UNIXTIME;
}
void KOSocket::OnRead()
{
Packet pkt;
for (;;)
{
if (m_remaining == 0)
{
if (GetReadBuffer().GetSize() < 5)
return; //check for opcode as well
uint16 header = 0;
GetReadBuffer().Read(&header, 2);
if (header != 0x55AA)
{
TRACE("%s: Got packet without header 0x55AA, got 0x%X\n", GetRemoteIP().c_str(), header);
goto error_handler;
}
GetReadBuffer().Read(&m_remaining, 2);
if (m_remaining == 0)
{
TRACE("%s: Got packet without an opcode, this should never happen.\n", GetRemoteIP().c_str());
goto error_handler;
}
}
if (m_remaining > GetReadBuffer().GetAllocatedSize())
{
TRACE("%s: Packet received which was %u bytes in size, maximum of %u.\n", GetRemoteIP().c_str(), m_remaining, GetReadBuffer().GetAllocatedSize());
goto error_handler;
}
if (m_remaining > GetReadBuffer().GetSize())
{
if (m_readTries > 4)
{
TRACE("%s: packet fragmentation count is over 4, disconnecting as they're probably up to something bad\n", GetRemoteIP().c_str());
goto error_handler;
}
m_readTries++;
return;
}
uint8 *in_stream = new uint8[m_remaining];
m_readTries = 0;
GetReadBuffer().Read(in_stream, m_remaining);
uint16 footer = 0;
GetReadBuffer().Read(&footer, 2);
if (footer != 0xAA55 || !DecryptPacket(in_stream, pkt))
{
TRACE("%s: Footer invalid (%X) or failed to decrypt.\n", GetRemoteIP().c_str(), footer);
delete [] in_stream;
goto error_handler;
}
delete [] in_stream;
m_lastResponse = UNIXTIME;
if (!HandlePacket(pkt))
{
TRACE("%s: Handler for packet %X returned false\n", GetRemoteIP().c_str(), pkt.GetOpcode());
#ifndef _DEBUG
goto error_handler;
#endif
}
// Update the time of the last (valid) response from the client.
m_remaining = 0;
}
return;
error_handler:
Disconnect();
}
bool KOSocket::DecryptPacket(uint8 *in_stream, Packet & pkt)
{
uint8* final_packet = nullptr;
if (isCryptoEnabled())
{
// Invalid packet (all encrypted packets need a CRC32 checksum!)
if (m_remaining < 4
// Invalid checksum
|| m_crypto.JvDecryptionWithCRC32(m_remaining, in_stream, in_stream) < 0
// Invalid sequence ID
|| ++m_sequence != *(uint32 *)(in_stream))
return false;
m_remaining -= 8; // remove the sequence ID & CRC checksum
final_packet = &in_stream[4];
}
else
{
final_packet = in_stream; // for simplicity :P
}
m_remaining--;
pkt = Packet(final_packet[0], (size_t)m_remaining);
if (m_remaining > 0)
{
pkt.resize(m_remaining);
memcpy((void*)pkt.contents(), &final_packet[1], m_remaining);
}
return true;
}
bool KOSocket::Send(Packet * pkt)
{
if (!IsConnected() || pkt->size() + 1 > GetWriteBuffer().GetAllocatedSize())
return false;
bool r;
uint8 opcode = pkt->GetOpcode();
uint8 * out_stream = nullptr;
uint16 len = (uint16)(pkt->size() + 1);
if (isCryptoEnabled())
{
len += 5;
out_stream = new uint8[len];
*(uint16 *)&out_stream[0] = 0x1efc;
*(uint16 *)&out_stream[2] = (uint16)(m_sequence); // this isn't actually incremented here
out_stream[4] = 0;
out_stream[5] = pkt->GetOpcode();
if (pkt->size() > 0)
memcpy(&out_stream[6], pkt->contents(), pkt->size());
m_crypto.JvEncryptionFast(len, out_stream, out_stream);
}
else
{
out_stream = new uint8[len];
out_stream[0] = pkt->GetOpcode();
if (pkt->size() > 0)
memcpy(&out_stream[1], pkt->contents(), pkt->size());
}
BurstBegin();
if (GetWriteBuffer().GetSpace() < size_t(len + 6))
{
TRACE("Disonnected due to insufficient buffer space [%d]. \n", GetSocketID());
BurstEnd();
Disconnect();
return false;
}
r = BurstSend((const uint8*)"\xaa\x55", 2);
if (r) r = BurstSend((const uint8*)&len, 2);
if (r) r = BurstSend((const uint8*)out_stream, len);
if (r) r = BurstSend((const uint8*)"\x55\xaa", 2);
if (r) BurstPush();
BurstEnd();
delete [] out_stream;
return r;
}
bool KOSocket::SendCompressed(Packet * pkt)
{
if (pkt->size() < 500)
return Send(pkt);
Packet result(WIZ_COMPRESS_PACKET);
uint32 inLength = pkt->size() + 1, outLength = inLength + LZF_MARGIN, crc;
uint8 *buffer = new uint8[inLength], *outBuffer = new uint8[outLength];
*buffer = pkt->GetOpcode();
if (pkt->size() > 0)
memcpy(buffer + 1, pkt->contents(), pkt->size());
crc = (uint32)crc32(buffer, inLength, 0);
outLength = lzf_compress(buffer, inLength, outBuffer, outLength);
result << outLength << inLength;
result << uint32(crc);
result.append(outBuffer, outLength);
delete [] buffer;
delete [] outBuffer;
return Send(&result);
}
void KOSocket::OnDisconnect()
{
if (GetRemoteIP() == "127.0.0.1")
printf("Connection closed from %s:%d\n", GetRemoteIP().c_str(), GetRemotePort());
}
void KOSocket::EnableCrypto()
{
#ifdef USE_CRYPTION
m_crypto.Init();
m_usingCrypto = true;
#endif
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include "SocketMgr.h"
#include "Packet.h"
#include "JvCryption.h"
extern "C"
{
#include "lzf.h"
}
// KO sockets time out after at least 30 seconds of inactivity. 6.1.2016
#define KOSOCKET_TIMEOUT (60)
// Allow up to 30 minutes for the player to create their character / the client to load.
#define KOSOCKET_LOADING_TIMEOUT (30 * 60)
class KOSocket : public Socket
{
public:
KOSocket(uint16 socketID, SocketMgr * mgr, SOCKET fd, uint32 sendBufferSize, uint32 recvBufferSize);
INLINE bool isCryptoEnabled() { return m_usingCrypto; };
INLINE uint16 GetSocketID() { return m_socketID; };
INLINE uint16 GetTargetID() { return m_targetID; };
INLINE time_t GetLastResponseTime() { return m_lastResponse; }
virtual void OnConnect();
virtual void OnRead();
virtual bool DecryptPacket(uint8 *in_stream, Packet & pkt);
virtual bool HandlePacket(Packet & pkt) = 0;
virtual bool Send(Packet * pkt);
virtual bool SendCompressed(Packet * pkt);
virtual void OnDisconnect();
void EnableCrypto();
protected:
CJvCryption m_crypto;
time_t m_lastResponse;
uint32 m_sequence;
uint16 m_remaining, m_socketID, m_targetID, bytesReceived;
uint8 m_readTries;
bool m_usingCrypto;
};
+160
View File
@@ -0,0 +1,160 @@
#pragma once
#include <map>
#include "RWLock.h"
#include "SocketMgr.h"
#include "KOSocket.h"
typedef std::map<uint16, KOSocket *> SessionMap;
template <class T>
class KOSocketMgr : public SocketMgr
{
public:
KOSocketMgr<T>() : m_server(nullptr) {}
virtual void InitSessions(uint16 sTotalSessions);
virtual bool Listen(uint16 sPort, uint16 sTotalSessions);
virtual bool Listen(std::string sIPAddress, uint16 sPort, uint16 sTotalSessions);
virtual void OnConnect(Socket *pSock);
virtual Socket *AssignSocket(SOCKET socket);
virtual void DisconnectCallback(Socket *pSock);
void RunServer()
{
SpawnWorkerThreads();
GetServer()->run();
}
// Send a packet to all active sessions
void SendAll(Packet * pkt)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
SessionMap & sessizmap = m_activeSessions;
for (auto itr = sessizmap.begin(); itr != sessizmap.end(); ++itr)
itr->second->Send(pkt);
}
void SendAllCompressed(Packet * result)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
SessionMap & sessMap = m_activeSessions;
for (auto itr = sessMap.begin(); itr != sessMap.end(); ++itr)
itr->second->SendCompressed(result);
}
ListenSocket<T> * GetServer() { return m_server; }
INLINE SessionMap & GetIdleSessionMap() { return m_idleSessions; }
INLINE SessionMap & GetActiveSessionMap() { return m_activeSessions; }
INLINE std::recursive_mutex& GetLock() { return m_lock; }
T * operator[] (uint16 id)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
auto itr = m_activeSessions.find(id);
if (itr != m_activeSessions.end())
return static_cast<T *>(itr->second);
return nullptr;
}
void Shutdown();
virtual ~KOSocketMgr();
protected:
SessionMap m_idleSessions, m_activeSessions;
std::recursive_mutex m_lock;
private:
ListenSocket<T> * m_server;
};
template <class T>
void KOSocketMgr<T>::InitSessions(uint16 sTotalSessions)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
for (uint16 i = 0; i < sTotalSessions; i++)
m_idleSessions.insert(std::make_pair(i, new T(i, this)));
}
template <class T>
bool KOSocketMgr<T>::Listen(uint16 sPort, uint16 sTotalSessions)
{
return Listen("0.0.0.0", sPort, sTotalSessions);
}
template <class T>
bool KOSocketMgr<T>::Listen(std::string sIPAddress, uint16 sPort, uint16 sTotalSessions)
{
if (m_server != nullptr)
return false;
CreateCompletionPort();
m_server = new ListenSocket<T>(this, sIPAddress.c_str(), sPort);
if (!m_server->IsOpen())
return false;
InitSessions(sTotalSessions);
return true;
}
template <class T>
Socket * KOSocketMgr<T>::AssignSocket(SOCKET socket)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
Socket *pSock = nullptr;
for (auto itr = m_idleSessions.begin(); itr != m_idleSessions.end(); itr++)
{
m_activeSessions.insert(std::make_pair(itr->first, itr->second));
pSock = itr->second;
m_idleSessions.erase(itr);
pSock->SetFd(socket);
break;
}
return pSock;
}
template <class T>
void KOSocketMgr<T>::OnConnect(Socket *pSock)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
auto itr = m_idleSessions.find(static_cast<KOSocket *>(pSock)->GetSocketID());
if (itr != m_idleSessions.end())
{
m_activeSessions.insert(std::make_pair(itr->first, itr->second));
m_idleSessions.erase(itr);
}
}
template <class T>
void KOSocketMgr<T>::DisconnectCallback(Socket *pSock)
{
std::lock_guard<std::recursive_mutex> lock(m_lock);
auto itr = m_activeSessions.find(static_cast<T *>(pSock)->GetSocketID());
if (itr != m_activeSessions.end())
{
m_idleSessions.insert(std::make_pair(itr->first, itr->second));
m_activeSessions.erase(itr);
}
}
template <class T>
void KOSocketMgr<T>::Shutdown()
{
if (m_bShutdown)
return;
if (m_server != nullptr)
delete m_server;
SocketMgr::Shutdown();
}
template <class T>
KOSocketMgr<T>::~KOSocketMgr()
{
Shutdown();
}
+130
View File
@@ -0,0 +1,130 @@
/*
* Multiplatform Async Network Library
* Copyright (c) 2007 Burlex
*
* ListenSocket<T>: Creates a socket listener on specified address and port,
* requires Update() to be called every loop.
*
*/
#pragma once
template <class T>
uint32 THREADCALL ListenSocketThread(void * lpParam)
{
ListenSocket<T> * ls = (ListenSocket<T> *)lpParam;
return ls->runnable() ? 0 : 1;
}
template<class T>
class ListenSocket
{
public:
ListenSocket(SocketMgr *socketMgr, const char * ListenAddress, uint32 Port) : m_threadRunning(false)
{
m_socket = WSASocket(AF_INET, SOCK_STREAM, 0, nullptr, 0, WSA_FLAG_OVERLAPPED);
// Enable blocking on the socket
SocketOps::Blocking(m_socket);
m_address.sin_family = AF_INET;
m_address.sin_port = ntohs((u_short)Port);
m_address.sin_addr.s_addr = htonl(INADDR_ANY);
m_opened = false;
if (strcmp(ListenAddress, "0.0.0.0"))
{
struct hostent * hostname = gethostbyname(ListenAddress);
if (hostname != nullptr)
memcpy(&m_address.sin_addr.s_addr, hostname->h_addr_list[0], hostname->h_length);
}
// bind. well, attempt to...
int ret = ::bind(m_socket, (const sockaddr*)&m_address, sizeof(m_address));
if (ret != 0)
{
printf("Bind unsuccessful on port %u.\n", Port);
return;
}
ret = listen(m_socket, 5);
if (ret != 0)
{
printf("Unable to listen on port %u.\n", Port);
return;
}
m_opened = true;
m_cp = socketMgr->GetCompletionPort();
m_socketMgr = socketMgr;
}
~ListenSocket() { Close(); }
bool run()
{
if (m_thread.isStarted())
return false;
m_thread.start(ListenSocketThread<T>, this);
return true;
}
bool runnable()
{
struct sockaddr_in m_tempAddress;
uint32 len = sizeof(sockaddr_in);
m_threadRunning = true;
while (m_opened && m_threadRunning)
{
//SOCKET aSocket = accept(m_socket, (sockaddr*)&m_tempAddress, (socklen_t*)&len);
SOCKET aSocket = WSAAccept(m_socket, (sockaddr*)&m_tempAddress, (socklen_t*)&len, 0, 0);
if (aSocket == INVALID_SOCKET)
{
//sleep(10); // Don't kill the CPU!
continue;
}
// Attempt to assign the socket to an available session
Socket *socket = m_socketMgr->AssignSocket(aSocket);
// No available sessions... unfortunately, we're going to have to let you go.
if (socket == nullptr)
{
SocketOps::CloseSocket(aSocket);
continue;
}
socket->SetCompletionPort(m_cp);
socket->Accept(&m_tempAddress);
}
return true;
}
void Close()
{
// prevent a race condition here.
bool mo = m_opened;
m_opened = false;
m_threadRunning = false;
if (mo)
SocketOps::CloseSocket(m_socket);
m_thread.waitForExit();
}
INLINE bool IsOpen() { return m_opened; }
INLINE HANDLE GetCompletionPort() { return m_cp; }
private:
bool m_threadRunning;
Thread m_thread;
HANDLE m_cp;
SocketMgr *m_socketMgr;
SOCKET m_socket;
struct sockaddr_in m_address;
bool m_opened;
};
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "CircularBuffer.h"
#include "SocketDefines.h"
#include "SocketOps.h"
#include "Socket.h"
#include "SocketMgr.h"
#include "ListenSocketWin32.h"
#include "JvCryption.h"
#include "KOSocket.h"
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "ByteBuffer.h"
#define CRYPT_KEY 129
class Packet : public ByteBuffer
{
public:
INLINE Packet() : ByteBuffer(), m_opcode(0) { }
INLINE Packet(uint8 opcode) : ByteBuffer(4096), m_opcode(opcode) {}
INLINE Packet(uint8 opcode, size_t res) : ByteBuffer(res), m_opcode(opcode) {}
INLINE Packet(const Packet &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) {}
INLINE Packet(uint8 opcode, uint8 subOpcode) : m_opcode(opcode)
{
append(&subOpcode, 1);
}
//! Clear packet and set opcode all in one mighty blow
INLINE void Initialize(uint8 opcode)
{
clear();
m_opcode = opcode;
}
INLINE uint8 GetOpcode() const { return m_opcode; }
INLINE void SetOpcode(uint8 opcode) { m_opcode = opcode; }
INLINE uint8 GetByte(uint16 sira) const { return _storage[sira]; }
INLINE void SetByte(uint16 sira,uint8 val) { _storage[sira] = val; }
protected:
uint8 m_opcode;
};
+38
View File
@@ -0,0 +1,38 @@
#include "stdafx.h"
#include "RWLock.h"
RWLock::RWLock()
{
_readers = _writers = 0;
}
void RWLock::AcquireReadLock()
{
_cond.BeginSynchronized();
_readers++;
_cond.EndSynchronized();
}
void RWLock::ReleaseReadLock()
{
_cond.BeginSynchronized();
if (!(--_readers))
if(_writers)
_cond.Signal();
_cond.EndSynchronized();
}
void RWLock::AcquireWriteLock()
{
_cond.BeginSynchronized();
_writers++;
if (_readers)
_cond.Wait();
}
void RWLock::ReleaseWriteLock()
{
if (--_writers)
_cond.Signal();
_cond.EndSynchronized();
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "Condition.h"
class RWLock
{
public:
RWLock();
void AcquireReadLock();
void ReleaseReadLock();
void AcquireWriteLock();
void ReleaseWriteLock();
private:
Condition _cond;
volatile unsigned int _readers;
volatile unsigned int _writers;
};
+19
View File
@@ -0,0 +1,19 @@
#include "stdafx.h"
#include "ReferenceObject.h"
ReferenceObject::ReferenceObject()
: m_refCount(0)
{
IncRef();
}
void ReferenceObject::IncRef()
{
++m_refCount;
}
void ReferenceObject::DecRef()
{
if (m_refCount.decrement() == 0)
delete this;
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
class ReferenceObject
{
public:
ReferenceObject();
// Increment the reference count
void IncRef();
// Decrease the reference count and delete the object if it hits 0 (i.e. no more references).
void DecRef();
virtual ~ReferenceObject() {}
private:
Atomic<uint32> m_refCount;
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
DebugUtils.cpp
Ini.cpp
F:\005SERVER\server source\shared\DebugUtils.cpp(1,10): error C1083: Cannot open precompiled header file: 'Release\shared.pch': No such file or directory
SMDFile.cpp
F:\005SERVER\server source\shared\Ini.cpp(1,10): error C1083: Cannot open precompiled header file: 'Release\shared.pch': No such file or directory
stdafx.cpp
F:\005SERVER\server source\shared\SMDFile.cpp(1,10): error C1083: Cannot open precompiled header file: 'Release\shared.pch': No such file or directory
TimeThread.cpp
F:\005SERVER\server source\shared\stdafx.cpp(1,10): error C1083: Cannot open precompiled header file: 'Release\shared.pch': No such file or directory
F:\005SERVER\server source\shared\TimeThread.cpp(1,10): error C1083: Cannot open precompiled header file: 'Release\shared.pch': No such file or directory
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
#TargetFrameworkVersion=v4.0:PlatformToolSet=v142:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
Release|Win32|F:\005SERVER\server source\|
Binary file not shown.
Binary file not shown.
+223
View File
@@ -0,0 +1,223 @@
#include "stdafx.h"
#include "../N3BASE/N3ShapeMgr.h"
#include "STLMapOnlyLoad.h"
#include "database/structs.h"
#include <set>
#include "SMDFile.h"
SMDFile::SMDMap SMDFile::s_loadedMaps;
SMDFile::SMDFile() : m_ppnEvent(nullptr), m_fHeight(nullptr),
m_nXRegion(0), m_nZRegion(0), m_nMapSize(0), m_fUnitDist(0.0f),
m_N3ShapeMgr(new CN3ShapeMgr())
{
}
SMDFile *SMDFile::Load(std::string mapName, bool bLoadWarpsAndRegeneEvents /*= false*/)
{
// case insensitive filenames, allowing for database inconsistency...
STRTOLOWER(mapName);
// Look to see if that SMD file has been loaded already
SMDMap::iterator itr = s_loadedMaps.find(mapName);
// If it's been loaded already, we don't need to do anything.
if (itr != s_loadedMaps.end())
{
// Add another reference.
itr->second->IncRef();
return itr->second;
}
// Map hasn't already been loaded
std::string filename = string_format(MAP_DIR "%s", mapName.c_str());
// Does this file exist/can it be opened?
FILE *fp = fopen(filename.c_str(), "rb");
if (fp == nullptr)
{
printf("ERROR: %s does not exist or no permission to access.\n", filename.c_str());
return nullptr;
}
// Try to load the file now.
SMDFile *smd = new SMDFile();
if (!smd->LoadMap(fp, mapName, bLoadWarpsAndRegeneEvents))
{
// Problem? Make sure we clean up after ourselves.
smd->DecRef(); // it's the only reference anyway
smd = nullptr;
}
else
{
// Loaded fine, so now add it to the map.
s_loadedMaps.insert(std::make_pair(mapName, smd));
}
fclose(fp);
return smd;
}
void SMDFile::OnInvalidMap()
{
printf("\n ** An error has occurred **\n\n");
printf("ERROR: %s is not a valid map file.\n\n", m_MapName.c_str());
printf("Previously, we ignored all invalid map behaviour, however this only hides\n");
printf("very real problems - especially with things like AI pathfinding.\n\n");
printf("This problem is most likely occur with maps tweaked to use a different\n");
printf("map size. Unfortunately, doing this means data after that (almost everything)\n");
printf("becomes corrupt, which is known to cause extremely 'unusual' buggy behaviour.\n\n");
printf("It is recommended you use a map built for this zone, or at the very least,\n");
printf("you should use a map originally built for the same zone size.\n\n");
ASSERT(0);
}
bool SMDFile::LoadMap(FILE *fp, std::string & mapName, bool bLoadWarpsAndRegeneEvents)
{
m_MapName = mapName;
LoadTerrain(fp);
m_N3ShapeMgr->Create((m_nMapSize - 1)*m_fUnitDist, (m_nMapSize-1)*m_fUnitDist);
if (!m_N3ShapeMgr->LoadCollisionData(fp)
|| (m_nMapSize - 1) * m_fUnitDist != m_N3ShapeMgr->Width()
|| (m_nMapSize - 1) * m_fUnitDist != m_N3ShapeMgr->Height())
return false;
int mapwidth = (int)m_N3ShapeMgr->Width();
m_nXRegion = (int)(mapwidth / VIEW_DISTANCE) + 1;
m_nZRegion = (int)(mapwidth / VIEW_DISTANCE) + 1;
LoadObjectEvent(fp);
LoadMapTile(fp);
if (bLoadWarpsAndRegeneEvents)
{
LoadRegeneEvent(fp);
LoadWarpList(fp);
}
return true;
}
void SMDFile::LoadTerrain(FILE *fp)
{
if (fread(&m_nMapSize, sizeof(m_nMapSize), 1, fp) != 1
|| fread(&m_fUnitDist, sizeof(m_fUnitDist), 1, fp) != 1)
return OnInvalidMap();
m_fHeight = new float[m_nMapSize * m_nMapSize];
if (fread(m_fHeight, sizeof(float) * m_nMapSize * m_nMapSize, 1, fp) != 1)
OnInvalidMap();
}
void SMDFile::LoadObjectEvent(FILE *fp)
{
int iEventObjectCount = 0;
if (fread(&iEventObjectCount, sizeof(int), 1, fp) != 1)
return OnInvalidMap();
// Load on K_OBJECTPOS table, this is set fd to last pointer...
for (int i = 0; i < iEventObjectCount; i++)
{
if (fread((new _OBJECT_EVENT), 24, 1, fp) != 1)
return OnInvalidMap();
}
}
void SMDFile::LoadMapTile(FILE *fp)
{
m_ppnEvent = new short[m_nMapSize * m_nMapSize];
if (fread(m_ppnEvent, sizeof(short) * m_nMapSize * m_nMapSize, 1, fp) != 1)
return OnInvalidMap();
}
void SMDFile::LoadRegeneEvent(FILE *fp)
{
int iEventObjectCount = 0;
if (fread(&iEventObjectCount, sizeof(iEventObjectCount), 1, fp) != 1)
return OnInvalidMap();
for (int i = 0; i < iEventObjectCount; i++)
{
_REGENE_EVENT *pEvent = new _REGENE_EVENT;
if (fread(pEvent, sizeof(_REGENE_EVENT) - sizeof(pEvent->sRegenePoint), 1, fp) != 1)
return OnInvalidMap();
pEvent->sRegenePoint = i;
if (pEvent->sRegenePoint < 0
|| !m_ObjectRegeneArray.PutData(pEvent->sRegenePoint, pEvent))
delete pEvent;
}
}
void SMDFile::LoadWarpList(FILE *fp)
{
int WarpCount = 0;
if (fread(&WarpCount, sizeof(WarpCount), 1, fp) != 1)
return OnInvalidMap();
for (int i = 0; i < WarpCount; i++)
{
_WARP_INFO *pWarp = new _WARP_INFO;
if (fread(pWarp, sizeof(_WARP_INFO), 1, fp) != 1)
{
// NOTE: Some SMDs are so horribly broken warps are incomplete.
// This will stop this (reasonably) normal use case from behaving any differently.
if (feof(fp))
return;
return OnInvalidMap();
}
if (pWarp->sWarpID == 0
|| !m_WarpArray.PutData(pWarp->sWarpID, pWarp))
delete pWarp;
}
}
void SMDFile::GetWarpList(int warpGroup, std::set<_WARP_INFO *> & warpEntries)
{
foreach_stlmap_nolock (itr, m_WarpArray)
{
_WARP_INFO *pWarp = itr->second;
if (pWarp == nullptr || (pWarp->sWarpID / 10) != warpGroup)
continue;
warpEntries.insert(pWarp);
}
}
bool SMDFile::IsValidPosition(float x, float z, float y)
{
// TODO: Implement more thorough check
return (x < m_N3ShapeMgr->Width() && z < m_N3ShapeMgr->Height());
}
int SMDFile::GetEventID(int x, int z)
{
if (x < 0 || x >= m_nMapSize || z < 0 || z >= m_nMapSize)
return -1;
return m_ppnEvent[x * m_nMapSize + z];
}
SMDFile::~SMDFile()
{
if (m_ppnEvent != nullptr)
{
delete [] m_ppnEvent;
m_ppnEvent = nullptr;
}
if (m_fHeight != nullptr)
{
delete[] m_fHeight;
m_fHeight = nullptr;
}
delete m_N3ShapeMgr;
}
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include "ReferenceObject.h"
class CUser;
typedef CSTLMapOnlyLoad <_OBJECT_EVENT> ObjectEventArray;
typedef CSTLMapOnlyLoad <_REGENE_EVENT> ObjectRegeneArray;
typedef CSTLMapOnlyLoad <_WARP_INFO> WarpArray;
class CN3ShapeMgr;
class SMDFile : public ReferenceObject
{
public:
SMDFile();
static SMDFile *Load(std::string mapName, bool bLoadWarpsAndRegeneEvents = false /* AI server doesn't need them */);
void OnInvalidMap();
bool LoadMap(FILE *fp, std::string & mapName, bool bLoadWarpsAndRegeneEvents /* AI server doesn't need them */);
void LoadTerrain(FILE *fp);
void LoadObjectEvent(FILE *fp);
void LoadMapTile(FILE *fp);
void LoadRegeneEvent(FILE *fp);
void LoadWarpList(FILE *fp);
bool IsValidPosition(float x, float z, float y);
bool CheckEvent( float x, float z, CUser* pUser = nullptr );
int GetEventID(int x, int z);
INLINE int GetMapSize() { return m_nMapSize - 1; }
INLINE float GetUnitDistance() { return m_fUnitDist; }
INLINE int GetXRegionMax() { return m_nXRegion - 1; }
INLINE int GetZRegionMax() { return m_nZRegion - 1; }
INLINE short * GetEventIDs() { return m_ppnEvent; }
INLINE ObjectEventArray * GetObjectEventArray() { return &m_ObjectEventArray; }
INLINE _OBJECT_EVENT * GetObjectEvent(int objectindex) { return m_ObjectEventArray.GetData(objectindex); }
INLINE _REGENE_EVENT * GetRegeneEvent(int objectindex) { return m_ObjectRegeneArray.GetData(objectindex); }
INLINE _WARP_INFO * GetWarp(int warpID) { return m_WarpArray.GetData(warpID); }
void GetWarpList(int warpGroup, std::set<_WARP_INFO *> & warpEntries);
virtual ~SMDFile();
private:
std::string m_MapName;
short* m_ppnEvent;
WarpArray m_WarpArray;
ObjectEventArray m_ObjectEventArray;
ObjectRegeneArray m_ObjectRegeneArray;
CN3ShapeMgr *m_N3ShapeMgr;
float* m_fHeight;
int m_nXRegion, m_nZRegion;
int m_nMapSize; // Grid Unit ex) 4m
float m_fUnitDist; // i Grid Distance
typedef std::map<std::string, SMDFile *> SMDMap;
static SMDMap s_loadedMaps;
#if defined(GAMESERVER)
friend class C3DMap;
#elif defined(AI_SERVER)
friend class MAP;
#endif
};
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#include <map>
template <class T>
class CSTLMap
{
public:
typedef typename std::map<uint32, T*>::iterator Iterator;
std::map<uint32, T*> m_UserTypeMap;
std::recursive_mutex m_lock;
int GetSize()
{
Guard lock(m_lock);
return m_UserTypeMap.size();
}
bool IsExist(uint32 key)
{
Guard lock(m_lock);
return (m_UserTypeMap.find(key) != m_UserTypeMap.end());
}
bool IsEmpty()
{
Guard lock(m_lock);
return m_UserTypeMap.empty();
}
bool PutData(uint32 key_value, T* pData)
{
Guard lock(m_lock);
return m_UserTypeMap.insert(std::make_pair(key_value, pData)).second;
}
T* GetData(uint32 key_value)
{
Guard lock(m_lock);
auto itr = m_UserTypeMap.find(key_value);
return (itr != m_UserTypeMap.end() ? itr->second : nullptr);
}
void DeleteData(uint32 key_value)
{
Guard lock(m_lock);
auto itr = m_UserTypeMap.find(key_value);
if (itr!= m_UserTypeMap.end())
{
delete itr->second;
m_UserTypeMap.erase(itr);
}
}
void DeleteAllData()
{
Guard lock(m_lock);
if (m_UserTypeMap.empty())
return;
foreach (itr, m_UserTypeMap)
delete itr->second;
m_UserTypeMap.clear();
}
~CSTLMap() { DeleteAllData(); }
};
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#include <map>
template <class T>
class CSTLMapOnlyLoad
{
public:
typedef typename std::map<uint32, T*>::iterator Iterator;
std::map<uint32, T*> m_UserTypeMap;
std::recursive_mutex m_lock;
int GetSize()
{
Guard lock(m_lock);
return m_UserTypeMap.size();
}
bool IsExist(uint32 key)
{
Guard lock(m_lock);
return (m_UserTypeMap.find(key) != m_UserTypeMap.end());
}
bool IsEmpty()
{
Guard lock(m_lock);
return m_UserTypeMap.empty();
}
bool PutData(uint32 key_value, T* pData)
{
Guard lock(m_lock);
return m_UserTypeMap.insert(std::make_pair(key_value, pData)).second;
}
T* GetData(uint32 key_value)
{
Guard lock(m_lock);
auto itr = m_UserTypeMap.find(key_value);
return (itr != m_UserTypeMap.end() ? itr->second : nullptr);
}
void DeleteData(uint32 key_value)
{
Guard lock(m_lock);
auto itr = m_UserTypeMap.find(key_value);
if (itr!= m_UserTypeMap.end())
{
delete itr->second;
m_UserTypeMap.erase(itr);
}
}
void DeleteAllData()
{
Guard lock(m_lock);
if (m_UserTypeMap.empty())
return;
foreach (itr, m_UserTypeMap)
delete itr->second;
m_UserTypeMap.clear();
}
~CSTLMapOnlyLoad() { DeleteAllData(); }
};
+139
View File
@@ -0,0 +1,139 @@
#include "stdafx.h"
#include "SocketMgr.h"
#pragma warning(disable:4996)
Socket::Socket(SOCKET fd, uint32 sendbuffersize, uint32 recvbuffersize)
: m_fd(fd), m_connected(false), m_deleted(false), m_socketMgr(nullptr)
{
// Allocate buffers
readBuffer.Allocate(recvbuffersize);
writeBuffer.Allocate(sendbuffersize);
// IOCP member variables
m_completionPort = 0;
m_writeLock = 0;
// Check for needed fd allocation.
if (m_fd == 0)
m_fd = SocketOps::CreateTCPFileDescriptor();
}
bool Socket::Connect(const char * Address, uint32 Port)
{
struct hostent * ci = gethostbyname(Address);
if (ci == 0)
return false;
m_client.sin_family = ci->h_addrtype;
m_client.sin_port = ntohs((u_short)Port);
memcpy(&m_client.sin_addr.s_addr, ci->h_addr_list[0], ci->h_length);
SocketOps::Blocking(m_fd);
if (m_fd == 0)
m_fd = SocketOps::CreateTCPFileDescriptor();
if (connect(m_fd, (const sockaddr*)&m_client, sizeof(m_client)) == -1)
return false;
// at this point the connection was established
m_completionPort = m_socketMgr->GetCompletionPort();
_OnConnect();
return true;
}
void Socket::Accept(sockaddr_in * address)
{
memcpy(&m_client, address, sizeof(*address));
_OnConnect();
}
void Socket::_OnConnect()
{
// set common parameters on the file descriptor
m_connected = true;
m_writeLockMutex.lock();
m_writeLock = 0;
m_writeLockMutex.unlock();
AssignToCompletionPort();
m_socketMgr->OnConnect(this);
// Call virtual onconnect
OnConnect();
//printf("_OnConnect %s:%d\n",GetRemoteIP().c_str(),GetRemotePort());
// Setting the read event up after calling OnConnect() ensures OnConnect() & subsequent connection setup code is run first (which is NOT GUARANTEED otherwise)
SetupReadEvent();
}
bool Socket::Send(const uint8 * Bytes, uint32 Size)
{
bool rv;
// This is really just a wrapper for all the burst stuff.
BurstBegin();
rv = BurstSend(Bytes, Size);
if (rv)
BurstPush();
BurstEnd();
return rv;
}
bool Socket::BurstSend(const uint8 * Bytes, uint32 Size)
{
return writeBuffer.Write(Bytes, Size);
}
std::string Socket::GetRemoteIP()
{
char* ip = (char*)inet_ntoa(m_client.sin_addr);
if (ip != nullptr)
return std::string(ip);
return std::string("noip");
}
void Socket::Disconnect()
{
if (!IsConnected())
return;
m_connected = false;
m_readEvent.Unmark();
// Call virtual ondisconnect
OnDisconnect();
GetSocketMgr()->OnDisconnect(this);
SocketOps::CloseSocket(m_fd);
m_fd = 0;
m_writeLockMutex.lock();
m_writeLock = 0;
m_writeLockMutex.unlock();
// Reset the read/write buffers
GetReadBuffer().Remove(GetReadBuffer().GetSize());
GetWriteBuffer().Remove(GetWriteBuffer().GetSize());
}
void Socket::Delete()
{
if (IsDeleted())
return;
m_deleted = true;
if (IsConnected())
Disconnect();
delete this;
}
Socket::~Socket()
{
}

Some files were not shown because too many files have changed in this diff Show More