Fix Linux compilation errors for LoginServer

Major fixes for Linux compatibility:
- Added comprehensive Linux socket type definitions to stdafx.h
- Created SocketOpsLinux.cpp with Linux socket operations implementation
- Added ListenSocketLinux.h with epoll-based socket listening
- Updated Network.h to conditionally include platform-specific headers
- Modified SocketDefines.h to support both Windows OVERLAPPED and Linux equivalents
- Updated CMakeLists.txt to use correct platform-specific source files
- Added additional socket constants and error code mappings for Linux

These changes address the compilation errors related to:
- Missing SOCKET, HANDLE, OVERLAPPED type definitions
- Windows-specific socket functions (WSASocket, closesocket, etc.)
- Platform-specific listen socket implementations
- Socket operations and error handling

The LoginServer should now compile successfully on Linux while maintaining Windows compatibility.
This commit is contained in:
Your Name 2025-08-29 22:10:58 +03:00
parent 59b331458c
commit e5a1ca68e7
7 changed files with 3834 additions and 4 deletions

View File

@ -68,6 +68,10 @@ if(WIN32)
../shared/SocketWin32.cpp
../shared/SocketOpsWin32.cpp
)
else()
list(APPEND SHARED_SOURCES
../shared/SocketOpsLinux.cpp
)
endif()
# Create executable

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
#pragma once
#ifndef _WIN32
// Linux-specific listen socket implementation
#include <sys/epoll.h>
#include <pthread.h>
template <class T>
class ListenSocket
{
public:
ListenSocket()
{
m_socket = -1;
m_epfd = -1;
m_shutdown = false;
m_socketMgr = nullptr;
}
~ListenSocket()
{
Close();
}
bool Open(uint32 port, const char * hostname, uint32 listenBacklogSize, uint32 sendBufferSize, uint32 recvBufferSize)
{
// Create socket
m_socket = socket(AF_INET, SOCK_STREAM, 0);
if (m_socket == INVALID_SOCKET)
return false;
// Set socket options
int arg = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg));
// Set non-blocking
SocketOps::Nonblocking(m_socket);
// Disable buffering
SocketOps::DisableBuffering(m_socket);
// Bind socket
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (hostname && strlen(hostname) > 0)
{
struct hostent * hostname_entry = gethostbyname(hostname);
if (hostname_entry == nullptr)
{
close(m_socket);
return false;
}
memcpy(&address.sin_addr.s_addr, hostname_entry->h_addr_list[0], hostname_entry->h_length);
}
else
{
address.sin_addr.s_addr = htonl(INADDR_ANY);
}
if (bind(m_socket, (struct sockaddr*)&address, sizeof(address)) == SOCKET_ERROR)
{
close(m_socket);
return false;
}
// Listen
if (listen(m_socket, listenBacklogSize) == SOCKET_ERROR)
{
close(m_socket);
return false;
}
// Create epoll instance
m_epfd = epoll_create1(0);
if (m_epfd == -1)
{
close(m_socket);
return false;
}
// Add listen socket to epoll
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = m_socket;
if (epoll_ctl(m_epfd, EPOLL_CTL_ADD, m_socket, &ev) == -1)
{
close(m_epfd);
close(m_socket);
return false;
}
return true;
}
void Close()
{
m_shutdown = true;
if (m_socket != INVALID_SOCKET)
{
SocketOps::CloseSocket(m_socket);
m_socket = INVALID_SOCKET;
}
if (m_epfd != -1)
{
close(m_epfd);
m_epfd = -1;
}
}
void SetSocketMgr(T * mgr)
{
m_socketMgr = mgr;
}
uint32 GetFileDescriptor() { return m_socket; }
void run()
{
const int MAX_EVENTS = 64;
struct epoll_event events[MAX_EVENTS];
struct sockaddr_in tempAddress;
socklen_t len;
while (!m_shutdown)
{
int nfds = epoll_wait(m_epfd, events, MAX_EVENTS, 100); // 100ms timeout
if (nfds == -1)
{
if (errno != EINTR)
break;
continue;
}
for (int i = 0; i < nfds; ++i)
{
if (events[i].data.fd == m_socket)
{
// New connection
len = sizeof(sockaddr_in);
int aSocket = accept(m_socket, (sockaddr*)&tempAddress, &len);
if (aSocket == INVALID_SOCKET)
continue;
Socket *socket = m_socketMgr->AssignSocket(aSocket);
if (socket == nullptr)
{
SocketOps::CloseSocket(aSocket);
continue;
}
socket->SetCompletionPort(m_epfd);
socket->Accept(&tempAddress);
}
}
}
}
static void* ListenThreadProcedure(void* lpParam)
{
ListenSocket<T> * ls = (ListenSocket<T> *)lpParam;
ls->run();
return nullptr;
}
private:
T * m_socketMgr;
int m_socket;
int m_epfd;
bool m_shutdown;
};
#endif // !_WIN32

View File

@ -5,7 +5,12 @@
#include "SocketOps.h"
#include "Socket.h"
#include "SocketMgr.h"
#include "ListenSocketWin32.h"
#ifdef _WIN32
#include "ListenSocketWin32.h"
#else
#include "ListenSocketLinux.h"
#endif
#include "JvCryption.h"
#include "KOSocket.h"

View File

@ -11,26 +11,42 @@ enum SocketIOEvent
class OverlappedStruct
{
public:
#ifdef _WIN32
OVERLAPPED m_overlap;
#else
// Linux equivalent using epoll data
struct {
unsigned long Internal;
unsigned long InternalHigh;
union {
struct {
unsigned long Offset;
unsigned long OffsetHigh;
};
void* Pointer;
};
int hEvent;
} m_overlap;
#endif
SocketIOEvent m_event;
Atomic<bool> m_inUse;
OverlappedStruct(SocketIOEvent ev) : m_event(ev)
{
memset(&m_overlap, 0, sizeof(OVERLAPPED));
memset(&m_overlap, 0, sizeof(m_overlap));
m_inUse = false;
};
OverlappedStruct()
{
memset(&m_overlap, 0, sizeof(OVERLAPPED));
memset(&m_overlap, 0, sizeof(m_overlap));
m_inUse = false;
}
INLINE void Reset(SocketIOEvent ev)
{
memset(&m_overlap, 0, sizeof(OVERLAPPED));
memset(&m_overlap, 0, sizeof(m_overlap));
m_event = ev;
}

View File

@ -0,0 +1,81 @@
#include "stdafx.h"
#include "SocketOps.h"
namespace SocketOps
{
#ifdef _WIN32
// Windows implementation (existing)
SOCKET CreateTCPFileDescriptor()
{
return WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
}
bool Nonblocking(SOCKET fd)
{
unsigned long arg = 1;
return (ioctlsocket(fd, FIONBIO, &arg) == 0);
}
bool Blocking(SOCKET fd)
{
unsigned long arg = 0;
return (ioctlsocket(fd, FIONBIO, &arg) == 0);
}
bool DisableBuffering(SOCKET fd)
{
int arg = 1;
return (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&arg, sizeof(int)) == 0);
}
bool EnableBuffering(SOCKET fd)
{
int arg = 0;
return (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&arg, sizeof(int)) == 0);
}
void CloseSocket(SOCKET fd)
{
shutdown(fd, SD_BOTH);
closesocket(fd);
}
#else
// Linux implementation
SOCKET CreateTCPFileDescriptor()
{
return socket(AF_INET, SOCK_STREAM, 0);
}
bool Nonblocking(SOCKET fd)
{
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) return false;
return (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
}
bool Blocking(SOCKET fd)
{
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) return false;
return (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == 0);
}
bool DisableBuffering(SOCKET fd)
{
int arg = 1;
return (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &arg, sizeof(int)) == 0);
}
bool EnableBuffering(SOCKET fd)
{
int arg = 0;
return (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &arg, sizeof(int)) == 0);
}
void CloseSocket(SOCKET fd)
{
shutdown(fd, SHUT_RDWR);
close(fd);
}
#endif
}

View File

@ -21,12 +21,14 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <dirent.h>
#define THREADCALL
@ -42,8 +44,46 @@
// Windows types for Linux
typedef int BOOL;
typedef unsigned long DWORD;
typedef int SOCKET;
typedef int HANDLE;
typedef void* LPVOID;
typedef unsigned long* LPDWORD;
#define TRUE 1
#define FALSE 0
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define INVALID_HANDLE_VALUE -1
// Windows socket functions mapping to Linux
#define WSASocket(af, type, protocol, lpProtocolInfo, g, dwFlags) socket(af, type, protocol)
#define WSAAccept(s, addr, addrlen, lpfnCondition, dwCallbackData) accept(s, addr, addrlen)
#define WSAGetLastError() errno
#define closesocket(s) close(s)
#define ioctlsocket(s, cmd, argp) ioctl(s, cmd, argp)
#define SD_BOTH SHUT_RDWR
#define FIONBIO O_NONBLOCK
// Additional socket constants
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAECONNRESET ECONNRESET
#define WSAENOTCONN ENOTCONN
// OVERLAPPED structure equivalent for Linux (using epoll)
typedef struct {
unsigned long Internal;
unsigned long InternalHigh;
union {
struct {
unsigned long Offset;
unsigned long OffsetHigh;
};
void* Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
#define CONTAINING_RECORD(address, type, field) \
((type *)((char*)(address) - (char*)&(((type *)0)->field)))
#endif
#if defined(_DEBUG) || defined(DEBUG)