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:
parent
59b331458c
commit
e5a1ca68e7
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -5,7 +5,12 @@
|
|||
#include "SocketOps.h"
|
||||
#include "Socket.h"
|
||||
#include "SocketMgr.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "ListenSocketWin32.h"
|
||||
#else
|
||||
#include "ListenSocketLinux.h"
|
||||
#endif
|
||||
|
||||
#include "JvCryption.h"
|
||||
#include "KOSocket.h"
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue