mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 12:18:27 +00:00
More file renames.
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#include "debug.h"
|
||||
#include "TCPServer.h"
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
#define SERVER_LOOP_GRANULARITY 3 //# of ms between checking our socket/queues
|
||||
|
||||
BaseTCPServer::BaseTCPServer(uint16 in_port) {
|
||||
NextID = 1;
|
||||
pPort = in_port;
|
||||
sock = 0;
|
||||
pRunLoop = true;
|
||||
#ifdef _WINDOWS
|
||||
_beginthread(BaseTCPServer::TCPServerLoop, 0, this);
|
||||
#else
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, &BaseTCPServer::TCPServerLoop, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
BaseTCPServer::~BaseTCPServer() {
|
||||
StopLoopAndWait();
|
||||
}
|
||||
|
||||
void BaseTCPServer::StopLoopAndWait() {
|
||||
MRunLoop.lock();
|
||||
if(pRunLoop) {
|
||||
pRunLoop = false;
|
||||
MRunLoop.unlock();
|
||||
//wait for loop to stop.
|
||||
MLoopRunning.lock();
|
||||
MLoopRunning.unlock();
|
||||
} else {
|
||||
MRunLoop.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseTCPServer::RunLoop() {
|
||||
bool ret;
|
||||
MRunLoop.lock();
|
||||
ret = pRunLoop;
|
||||
MRunLoop.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ThreadReturnType BaseTCPServer::TCPServerLoop(void* tmp) {
|
||||
#ifdef _WINDOWS
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
#endif
|
||||
if (tmp == 0) {
|
||||
THREAD_RETURN(nullptr);
|
||||
}
|
||||
BaseTCPServer* tcps = (BaseTCPServer*) tmp;
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Starting TCPServerLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
tcps->MLoopRunning.lock();
|
||||
while (tcps->RunLoop()) {
|
||||
Sleep(SERVER_LOOP_GRANULARITY);
|
||||
tcps->Process();
|
||||
}
|
||||
tcps->MLoopRunning.unlock();
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Ending TCPServerLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
THREAD_RETURN(nullptr);
|
||||
}
|
||||
|
||||
void BaseTCPServer::Process() {
|
||||
ListenNewConnections();
|
||||
}
|
||||
|
||||
void BaseTCPServer::ListenNewConnections() {
|
||||
SOCKET tmpsock;
|
||||
struct sockaddr_in from;
|
||||
struct in_addr in;
|
||||
unsigned int fromlen;
|
||||
unsigned short port;
|
||||
|
||||
from.sin_family = AF_INET;
|
||||
fromlen = sizeof(from);
|
||||
LockMutex lock(&MSock);
|
||||
#ifndef DARWIN // Corysia - On OSX, 0 is a valid fd.
|
||||
if (!sock)
|
||||
return;
|
||||
#else
|
||||
if (sock == -1) return;
|
||||
#endif
|
||||
|
||||
// Check for pending connects
|
||||
#ifdef _WINDOWS
|
||||
unsigned long nonblocking = 1;
|
||||
while ((tmpsock = accept(sock, (struct sockaddr*) &from, (int *) &fromlen)) != INVALID_SOCKET) {
|
||||
ioctlsocket (tmpsock, FIONBIO, &nonblocking);
|
||||
#else
|
||||
#ifdef __CYGWIN__
|
||||
while ((tmpsock = accept(sock, (struct sockaddr *) &from, (int *) &fromlen)) != INVALID_SOCKET) {
|
||||
#else
|
||||
while ((tmpsock = accept(sock, (struct sockaddr*) &from, &fromlen)) != INVALID_SOCKET) {
|
||||
#endif
|
||||
fcntl(tmpsock, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k
|
||||
setsockopt(tmpsock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
|
||||
port = from.sin_port;
|
||||
in.s_addr = from.sin_addr.s_addr;
|
||||
|
||||
// New TCP connection, this must consume the socket.
|
||||
CreateNewConnection(GetNextID(), tmpsock, in.s_addr, ntohs(from.sin_port));
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseTCPServer::Open(uint16 in_port, char* errbuf) {
|
||||
if (errbuf)
|
||||
errbuf[0] = 0;
|
||||
LockMutex lock(&MSock);
|
||||
if (sock != 0) {
|
||||
if (errbuf)
|
||||
snprintf(errbuf, TCPServer_ErrorBufferSize, "Listening socket already open");
|
||||
return false;
|
||||
}
|
||||
if (in_port != 0) {
|
||||
pPort = in_port;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
SOCKADDR_IN address;
|
||||
unsigned long nonblocking = 1;
|
||||
#else
|
||||
struct sockaddr_in address;
|
||||
#endif
|
||||
int reuse_addr = 1;
|
||||
|
||||
// Setup internet address information.
|
||||
// This is used with the bind() call
|
||||
memset((char *) &address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(pPort);
|
||||
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// Setting up TCP port for new TCP connections
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
if (errbuf)
|
||||
snprintf(errbuf, TCPServer_ErrorBufferSize, "socket(): INVALID_SOCKET");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Quag: dont think following is good stuff for TCP, good for UDP
|
||||
// Mis: SO_REUSEADDR shouldn't be a problem for tcp--allows you to restart
|
||||
// without waiting for conns in TIME_WAIT to die
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr));
|
||||
|
||||
|
||||
if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) {
|
||||
#ifdef _WINDOWS
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
sock = 0;
|
||||
if (errbuf)
|
||||
sprintf(errbuf, "bind(): <0");
|
||||
return false;
|
||||
}
|
||||
|
||||
int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
|
||||
#ifdef _WINDOWS
|
||||
ioctlsocket (sock, FIONBIO, &nonblocking);
|
||||
#else
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
|
||||
#ifdef _WINDOWS
|
||||
closesocket(sock);
|
||||
if (errbuf)
|
||||
snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %d", WSAGetLastError());
|
||||
#else
|
||||
close(sock);
|
||||
if (errbuf)
|
||||
snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %s", strerror(errno));
|
||||
#endif
|
||||
sock = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaseTCPServer::Close() {
|
||||
StopLoopAndWait();
|
||||
|
||||
LockMutex lock(&MSock);
|
||||
if (sock) {
|
||||
#ifdef _WINDOWS
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
sock = 0;
|
||||
}
|
||||
|
||||
bool BaseTCPServer::IsOpen() {
|
||||
MSock.lock();
|
||||
bool ret = (bool) (sock != 0);
|
||||
MSock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user