www.pudn.com > ntshell.rar > sockmgr.cpp
// sockmgr.cpp: implementation of the CSockManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "common.h"
#include "ntshell.h"
#include "sockmgr.h"
bool CSockManager::Inited = false;
CSockManager::PTEMP_BUFFER CSockManager::ptb = NULL;
CRITICAL_SECTION CSockManager::SendCS;
CRITICAL_SECTION CSockManager::RecvCS;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSockManager::CSockManager()
{
simCount = 0;
}
CSockManager::~CSockManager()
{
while (simCount)
{
FreeBuffer(&ppsim[--simCount]->sib);
delete ppsim[simCount];
}
}
int CSockManager::GetIoStateCode(SOCKET sock)
{
int index = GetSockIndex(sock);
return index == SOCKMGR_SOCK_NOT_FOUND ? index : ppsim[index]->status;
}
int CSockManager::GetSockIndex(SOCKET sock)
{
for (int i = 0; i < simCount; i++)
{
if (ppsim[i]->sock == sock)
return i;
}
return SOCKMGR_SOCK_NOT_FOUND;
}
PVOID CSockManager::GetSim(SOCKET sock)
{
int index = GetSockIndex(sock);
if (index == SOCKMGR_SOCK_NOT_FOUND)
return NULL;
return ppsim[index];
}
int CSockManager::InsertSock(SOCKET sock)
{
ppsim[simCount] = new SOCK_IO_MANAGER;
ppsim[simCount]->packsize = 0;
ppsim[simCount]->sock = sock;
ppsim[simCount]->status = SOCKMGR_IO_READY;
ppsim[simCount]->siblock = BUFFER_LOCKED_NONE;
if (ppsim[simCount] != NULL)
{
if (InitBuffer(&ppsim[simCount]->sib) == false)
{
delete ppsim[simCount];
return -1;
}
simCount++;
return simCount - 1;
}
return SOCKMGR_SOCK_NOT_FOUND;
}
void CSockManager::DeleteSock(SOCKET sock)
{
int index = GetSockIndex(sock);
if (index == SOCKMGR_SOCK_NOT_FOUND)
return;
simCount--;
FreeBuffer(&ppsim[index]->sib);
delete ppsim[index];
ppsim[index] = ppsim[simCount];
}
bool CSockManager::InitBuffer(PSOCK_IO_BUFFER psib, int BufferSize)
{
psib->maxlength = 0x200000;
psib->pointer = 0;
psib->datalength = 0;
if (BufferSize > psib->maxlength)
return false;
psib->length = (BufferSize + 0xfff) & 0xfffff000;
psib->buffer = (char *)VirtualAlloc(NULL, psib->maxlength, MEM_RESERVE, PAGE_READWRITE);
return psib->buffer == NULL ? false : true;
}
int CSockManager::ReadBuffer(SOCKET sock, char *buffer, int length)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
PSOCK_IO_BUFFER psib = &psim->sib;
if (length > psib->datalength - psib->pointer)
return SOCKMGR_SPACE_NOT_ENOUGH;
memcpy(buffer, psib->buffer + psib->pointer, length);
psib->pointer += length;
return SOCKMGR_SUCCESS;
}
int CSockManager::WriteBuffer(SOCKET sock, char *buffer, int length)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
PSOCK_IO_BUFFER psib = &psim->sib;
int used = psib->datalength;
int need = 0;
if (psib->buffer == NULL)
{
InitBuffer(psib);
}
if (psib->length - used < length)
{
if (psib->maxlength - used < length)
return SOCKMGR_SPACE_NOT_ENOUGH;
psib->length = (used + length + 0xfff) & 0xfffff000;
psib->buffer = (char *)VirtualAlloc(psib->buffer, psib->length, MEM_COMMIT, PAGE_READWRITE);
}
memcpy(psib->buffer + used, buffer, length);
psib->pointer += length;
psib->datalength += length;
return SOCKMGR_SUCCESS;
}
void CSockManager::FreeBuffer(PSOCK_IO_BUFFER psib)
{
VirtualFree(psib->buffer, 0, MEM_RELEASE);
psib->buffer = NULL;
psib->length = 0;
psib->pointer = 0;
psib->datalength = 0;
}
int CSockManager::SendPack(SOCKET sock)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
int ret;
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
if (psim->siblock != BUFFER_LOCKED_NONE &&
psim->siblock != BUFFER_LOCKED_SEND)
return SOCKMGR_BUFFER_LOCKED;
if (psim->status == SOCKMGR_IO_READY ||
psim->status == SOCKMGR_IO_READ_FINISH ||
psim->status == SOCKMGR_IO_WRITE_FINISH)
{
ret = send(psim->sock, (char *)&psim->sib.datalength, sizeof(psim->sib.datalength), 0);
if (ret == SOCKET_ERROR)
{
lastErrorCode = WSAGetLastError();
return SOCKMGR_SOCK_FAILED;
}
psim->status = SOCKMGR_IO_WRITING_PACKDATA;
psim->sib.pointer = 0;
}
if (psim->status != SOCKMGR_IO_WRITING_PACKDATA)
{
return SOCKMGR_INVALID_PROCESS;
}
psim->siblock = BUFFER_LOCKED_SEND;
ret = send(psim->sock, psim->sib.buffer + psim->sib.pointer, psim->sib.datalength - psim->sib.pointer, 0);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
lastErrorCode = WSAGetLastError();
psim->siblock = BUFFER_LOCKED_NONE;
return SOCKMGR_SOCK_FAILED;
}
}
psim->sib.pointer += ret;
if (psim->sib.pointer == psim->sib.datalength)
{
psim->status = SOCKMGR_IO_WRITE_FINISH;
psim->siblock = BUFFER_LOCKED_NONE;
psim->sib.pointer = 0;
psim->packsize = psim->sib.datalength;
return SOCKMGR_SUCCESS;
}
return SOCKMGR_PENDING;
}
int CSockManager::RecvPack(SOCKET sock)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
int ret, readed, packsize;
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
if (psim->siblock != BUFFER_LOCKED_NONE &&
psim->siblock != BUFFER_LOCKED_RECV)
return SOCKMGR_BUFFER_LOCKED;
if (psim->status == SOCKMGR_IO_READY ||
psim->status == SOCKMGR_IO_READ_FINISH ||
psim->status == SOCKMGR_IO_WRITE_FINISH ||
psim->status == SOCKMGR_IO_READING_PACKSIZE1 ||
psim->status == SOCKMGR_IO_READING_PACKSIZE2 ||
psim->status == SOCKMGR_IO_READING_PACKSIZE3)
{
switch (psim->status)
{
case SOCKMGR_IO_READY:
case SOCKMGR_IO_READ_FINISH:
case SOCKMGR_IO_WRITE_FINISH:
readed = 0;
break;
case SOCKMGR_IO_READING_PACKSIZE1:
readed = 1;
break;
case SOCKMGR_IO_READING_PACKSIZE2:
readed = 2;
break;
case SOCKMGR_IO_READING_PACKSIZE3:
readed = 3;
break;
}
packsize = psim->packsize;
ret = recv(psim->sock, (char *)&packsize + readed, sizeof(packsize) - readed, 0);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
lastErrorCode = WSAGetLastError();
return SOCKMGR_SOCK_FAILED;
}
}
if (ret == 0)
return SOCKMGR_SOCK_CLOSED;
psim->packsize = packsize;
switch (ret + readed)
{
case 1:
psim->status = SOCKMGR_IO_READING_PACKSIZE1;
return SOCKMGR_PENDING;
case 2:
psim->status = SOCKMGR_IO_READING_PACKSIZE2;
return SOCKMGR_PENDING;
case 3:
psim->status = SOCKMGR_IO_READING_PACKSIZE3;
return SOCKMGR_PENDING;
case 4:
psim->status = SOCKMGR_IO_READING_PACKDATA;
psim->packsize >>= 2;
psim->sib.pointer = 0;
break;
}
}
if (psim->status != SOCKMGR_IO_READING_PACKDATA)
return SOCKMGR_INVALID_PROCESS;
if (psim->packsize > psim->sib.length)
{
if (psim->packsize > psim->sib.maxlength)
return SOCKMGR_SPACE_NOT_ENOUGH;
psim->sib.length = (psim->packsize + 0xfff) & 0xfffff000;
psim->sib.buffer = (char *)VirtualAlloc(psim->sib.buffer, psim->sib.length, MEM_COMMIT, PAGE_READWRITE);
}
psim->siblock = BUFFER_LOCKED_RECV;
ret = recv(psim->sock, psim->sib.buffer + psim->sib.pointer, psim->packsize - psim->sib.pointer, 0);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
lastErrorCode = WSAGetLastError();
psim->siblock = BUFFER_LOCKED_NONE;
return SOCKMGR_SOCK_FAILED;
}
}
if (ret == 0)
{
psim->siblock = BUFFER_LOCKED_NONE;
return SOCKMGR_SOCK_CLOSED;
}
psim->sib.pointer += ret;
if (psim->sib.pointer >= psim->packsize)
{
psim->status = SOCKMGR_IO_READ_FINISH;
psim->siblock = BUFFER_LOCKED_NONE;
psim->sib.pointer = 0;
psim->sib.datalength = psim->packsize;
return SOCKMGR_SUCCESS;
}
return SOCKMGR_PENDING;
}
int CSockManager::OpenListenSock(char *bind_ip, int bind_port)
{
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_sock == INVALID_SOCKET)
{
return -1;
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(bind_port);
local.sin_addr.s_addr = inet_addr(bind_ip);
if (bind(listen_sock, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
{
closesocket(listen_sock);
return -1;
}
if (listen(listen_sock, MAX_CONNECT) == SOCKET_ERROR) //最大连接数量
{
closesocket(listen_sock);
return -1;
}
return 0;
}
int CSockManager::GetBufferDataSize(SOCKET sock)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return 0;
return psim->packsize;
}
int CSockManager::GetBufferHandle(SOCKET sock, void **buffer, int *length)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
if (psim->siblock != BUFFER_LOCKED_NONE &&
psim->siblock != BUFFER_LOCKED_USER)
return SOCKMGR_BUFFER_LOCKED;
psim->siblock = BUFFER_LOCKED_USER;
if (length != NULL)
*length = psim->sib.length;
*buffer = psim->sib.buffer;
return SOCKMGR_SUCCESS;
}
void CSockManager::ReleaseBufferHandle(SOCKET sock)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim != NULL && psim->siblock == BUFFER_LOCKED_USER)
psim->siblock = BUFFER_LOCKED_NONE;
}
int CSockManager::MovePointer(SOCKET sock, int move, int method)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return SOCKMGR_SOCK_NOT_FOUND;
if (psim->siblock != BUFFER_LOCKED_NONE &&
psim->siblock != BUFFER_LOCKED_USER)
return SOCKMGR_BUFFER_LOCKED;
switch (method)
{
case BUFFER_BEGIN:
psim->sib.pointer = move;
break;
case BUFFER_CURRENT:
psim->sib.pointer += move;
break;
case BUFFER_END:
psim->sib.pointer = psim->sib.datalength + move;
break;
}
return SOCKMGR_SUCCESS;
}
void CSockManager::CleanupBuffer(SOCKET sock)
{
PSOCK_IO_MANAGER psim = (PSOCK_IO_MANAGER)GetSim(sock);
if (psim == NULL)
return;
if (psim->siblock != BUFFER_LOCKED_NONE &&
psim->siblock != BUFFER_LOCKED_USER)
return;
psim->sib.pointer = 0;
psim->sib.datalength = 0;
}
char *CSockManager::GetErrorString()
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
lastErrorCode,
0,
(LPTSTR)&lpMsgBuf,
0,
NULL
);
return (char *)lpMsgBuf;
}
int CSockManager::SendPack(SOCKET sock, char *buffer, int length, int flags)
{
if (Inited == false)
{
InitializeCriticalSection(&SendCS);
InitializeCriticalSection(&RecvCS);
Inited = true;
}
PTEMP_BUFFER p = ptb;
int result = SOCKMGR_PENDING;
EnterCriticalSection(&SendCS);
while (p != NULL)
{
if (p->sock == sock && p->method == 1)
break;
p = p->next;
}
if (p != NULL && buffer != NULL)
{
LeaveCriticalSection(&SendCS);
return SOCKMGR_SOCK_LOCKED;
}
if (p == NULL)
{
if (buffer == NULL)
return SOCKMGR_NOT_BUFFER;
if (flags == 0)
{
p = (PTEMP_BUFFER)new char[sizeof(TEMP_BUFFER) + sizeof(PACK_TYPE_1) + length];
if (p == NULL)
return SOCKMGR_NOT_ENOUGH_MEMORY;
p->sock = sock;
p->buffer = (char *)p + sizeof(TEMP_BUFFER);
p->length = sizeof(PACK_TYPE_1) + length;
p->pointer = 0;
p->method = 1;
p->next = ptb;
ptb = p;
PPACK_TYPE_1 pack = (PPACK_TYPE_1)(p->buffer);
pack->dwPackType = 0;
pack->nPackSize = length;
memcpy(pack->bPackData, buffer, length);
}
else
{
p = (PTEMP_BUFFER)new char[sizeof(TEMP_BUFFER) + sizeof(PACK_TYPE_2) + length + 0x1000];
if (p == NULL)
return SOCKMGR_NOT_ENOUGH_MEMORY;
p->buffer = (char *)p + sizeof(TEMP_BUFFER);
PPACK_TYPE_2 pack = (PPACK_TYPE_2)(p->buffer);
if (flags & SOCKMGR_SEND_COMPRESS)
{
pack->bCompressed = TRUE;
pack->nPackSize = Lz77Compress(p->buffer, buffer, length, 2);
}
else
{
pack->bCompressed = FALSE;
pack->nPackSize = length;
}
if (flags & SOCKMGR_SEND_ENCRYPT)
{
rc5_encrypt(pack->bPackData, pack->bPackData, pack->nPackSize);
pack->bEncrypted = TRUE;
}
else
{
pack->bEncrypted = FALSE;
}
pack->dwPackType = 1;
pack->nOriginalSize = length;
pack->dwCrc32 = crc32(0, pack->bPackData, pack->nPackSize);
p->sock = sock;
p->length = sizeof(PACK_TYPE_2) + pack->nPackSize;
p->pointer = 0;
p->method = 1;
p->next = ptb;
ptb = p;
}
}
LeaveCriticalSection(&SendCS);
int ret = send(p->sock, p->buffer + p->pointer, p->length - p->pointer, 0);
if (ret == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
result = SOCKMGR_SOCK_FAILED;
goto cleanup;
}
}
p->pointer += ret;
if (p->pointer == p->length)
{
result = SOCKMGR_SUCCESS;
goto cleanup;
}
return SOCKMGR_PENDING;
cleanup:
EnterCriticalSection(&SendCS);
for (PTEMP_BUFFER *prev = &ptb; *prev != NULL; prev = &((*prev)->next))
{
if ((*prev)->sock == sock && (*prev)->method == 1)
{
*prev = (*prev)->next;
break;
}
}
delete [] p;
LeaveCriticalSection(&SendCS);
return result;
}
int CSockManager::RecvPack(SOCKET sock, IoCallBack funback, LPVOID funparam)
{
if (Inited == false)
{
InitializeCriticalSection(&SendCS);
InitializeCriticalSection(&RecvCS);
Inited = true;
}
PTEMP_BUFFER p = ptb;
int result = SOCKMGR_PENDING;
int ret;
EnterCriticalSection(&RecvCS);
while (p != NULL)
{
if (p->sock == sock && p->method == 2)
break;
p = p->next;
}
if (p == NULL)
{
p = new TEMP_BUFFER;
if (p == NULL)
{
LeaveCriticalSection(&RecvCS);
return SOCKMGR_NOT_ENOUGH_MEMORY;
}
p->sock = sock;
p->buffer = (char *)HeapAlloc(GetProcessHeap(), 0, sizeof(PACK_TYPE_1));
if (p->buffer == NULL)
{
delete p;
LeaveCriticalSection(&RecvCS);
return SOCKMGR_NOT_ENOUGH_MEMORY;
}
p->length = sizeof(PACK_TYPE_1);
p->pointer = 0;
p->method = 2;
p->funback = funback;
p->funparam = funparam;
p->next = ptb;
ptb = p;
}
LeaveCriticalSection(&RecvCS);
if (p->pointer < sizeof(PACK_TYPE_1))
{
int ret = recv(p->sock, p->buffer + p->pointer, sizeof(PACK_TYPE_1) - p->pointer, 0);
if (ret == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
result = SOCKMGR_SOCK_FAILED;
goto cleanup;
}
}
p->pointer += ret;
if (p->pointer < sizeof(PACK_TYPE_1))
return SOCKMGR_PENDING;
PPACK_TYPE_1 pack = (PPACK_TYPE_1)(p->buffer);
p->length = (pack->dwPackType == 0 ? sizeof(PACK_TYPE_1) : sizeof(PACK_TYPE_2)) + pack->nPackSize;
p->buffer = (char *)HeapReAlloc(GetProcessHeap(), 0, p->buffer, p->length);
if (p->buffer == NULL)
{
result = SOCKMGR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
ret = recv(p->sock, p->buffer + p->pointer, p->length - p->pointer, 0);
if (ret == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
return SOCKMGR_PENDING;
else
{
result = SOCKMGR_SOCK_FAILED;
goto cleanup;
}
}
p->pointer += ret;
if (p->pointer == p->length)
{
if (((PPACK_TYPE_1)p->buffer)->dwPackType == 0)
{
PPACK_TYPE_1 pack = (PPACK_TYPE_1)(p->buffer);
PACK_INFO pi;
pi.bCompress = false;
pi.bEncrypt = false;
pi.pData = (char *)pack->bPackData;
pi.nDataSize = pack->nPackSize;
pi.nPackSize = pack->nPackSize;
if (p->funback != NULL)
{
p->funback(&pi, p->funparam);
result = SOCKMGR_SUCCESS;
goto cleanup;
}
}
else
{
PPACK_TYPE_2 pack = (PPACK_TYPE_2)(p->buffer);
PACK_INFO pi;
pi.bCompress = pack->bCompressed ? true : false;
pi.bEncrypt = pack->bEncrypted ? true : false;
pi.pData = (char *)pack->bPackData;
pi.nDataSize = pack->nOriginalSize;
pi.nPackSize = pack->nPackSize;
if (crc32(0, (char *)pack->bPackData, pack->nPackSize) != pack->dwCrc32)
{
result = SOCKMGR_PACK_CRC_FAILED;
goto cleanup;
}
if (pack->bEncrypted != FALSE)
rc5_decrypt(pack->bPackData, pack->bPackData, pack->nPackSize);
if (pack->bCompressed != FALSE)
{
char *t = (char *)HeapAlloc(GetProcessHeap(), 0, pack->nOriginalSize);
if (t == NULL)
{
result = SOCKMGR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
Lz77Decompress(t, pack->bPackData, pack->nPackSize);
p->length = pack->nOriginalSize;
HeapFree(GetProcessHeap(), 0, p->buffer);
p->buffer = t;
pi.pData = t;
}
if (p->funback != NULL)
{
p->funback(&pi, p->funparam);
result = SOCKMGR_SUCCESS;
goto cleanup;
}
}
}
return SOCKMGR_PENDING;
cleanup:
EnterCriticalSection(&RecvCS);
for (PTEMP_BUFFER *prev = &ptb; *prev != NULL; prev = &((*prev)->next))
{
if ((*prev)->sock == sock && (*prev)->method == 2)
{
*prev = (*prev)->next;
break;
}
}
if (p->buffer != NULL)
HeapFree(GetProcessHeap(), 0, p->buffer);
delete p;
LeaveCriticalSection(&RecvCS);
return result;
}
void CSockManager::InterruptSend(SOCKET sock)
{
if (Inited == false)
return;
PTEMP_BUFFER p = NULL;
EnterCriticalSection(&SendCS);
for (PTEMP_BUFFER *prev = &ptb; *prev != NULL; prev = &((*prev)->next))
{
if ((*prev)->sock == sock && (*prev)->method == 1)
{
p = *prev;
*prev = (*prev)->next;
break;
}
}
if (p != NULL)
delete [] p;
LeaveCriticalSection(&SendCS);
}
void CSockManager::InterruptRecv(SOCKET sock)
{
if (Inited == false)
return;
PTEMP_BUFFER p = NULL;
EnterCriticalSection(&RecvCS);
for (PTEMP_BUFFER *prev = &ptb; *prev != NULL; prev = &((*prev)->next))
{
if ((*prev)->sock == sock && (*prev)->method == 2)
{
p = *prev;
*prev = (*prev)->next;
break;
}
}
if (p != NULL)
{
if (p->buffer != NULL)
HeapFree(GetProcessHeap(), 0, p->buffer);
delete p;
}
LeaveCriticalSection(&RecvCS);
}