EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
TCPServer.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Rewrite: Allan
25 */
26 
27 #include "eve-core.h"
28 
29 #include "network/TCPServer.h"
30 #include "log/LogNew.h"
31 #include "log/logsys.h"
32 #include "threading/Threading.h"
33 
35 const uint32 TCPSRV_LOOP_GRANULARITY = 5; /* 5ms */
36 
38 : mSock( nullptr ),
39  mPort( 0 )
40 {
41 }
42 
44 {
45  // Close socket
46  Close();
47  // Wait until worker thread terminates
48  WaitLoop();
49  /* delete thread here and remove from list */
50  sThread.RemoveThread(pthread_self());
51 }
52 
54 {
55  mMSock.Lock();
56  bool ret = (mSock != nullptr);
57  mMSock.Unlock();
58  return ret;
59 }
60 
61 bool BaseTCPServer::Open( uint16 port, char* errbuf )
62 {
63  if (errbuf != nullptr)
64  errbuf[0] = 0;
65 
66  // mutex lock
67  MutexLock lock( mMSock );
68 
69  if (IsOpen()) {
70  _log(TCP_SERVER__ERROR, "Open() - Listening socket already open" );
71  if (errbuf != nullptr)
72  snprintf( errbuf, TCPSRV_ERRBUF_SIZE, "Listening socket already open" );
73  return false;
74  } else {
75  mMSock.Unlock();
76  WaitLoop();
77  mMSock.Lock();
78  }
79 
80  // Setting up TCP port for new TCP connections
81  mSock = new Socket( AF_INET, SOCK_STREAM, 0 );
82 
83  unsigned int reuse_addr = 1;
84  mSock->setopt( SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof( reuse_addr ) );
85 
86  // Setup internet address information.
87  // This is used with the bind() call
88  sockaddr_in address = sockaddr_in();
89  memset( &address, 0, sizeof( address ) );
90  address.sin_family = AF_INET;
91  address.sin_port = htons( port );
92  address.sin_addr.s_addr = htonl( INADDR_ANY );
93 
94  if (mSock->bind((sockaddr*)&address, sizeof(address)) < 0) {
95  _log(TCP_SERVER__ERROR, "Open()::bind() < 0" );
96  if (errbuf)
97  snprintf( errbuf, TCPSRV_ERRBUF_SIZE, "%s", strerror( errno ) );
98  SafeDelete( mSock );
99  return false;
100  }
101 
102  unsigned int bufsize = 64 * 1024; // 64kbyte receive buffer, up from default of 8k
103  mSock->setopt( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof( bufsize ) );
104  mSock->fcntl( F_SETFL, O_NONBLOCK );
105  if (mSock->listen() == SOCKET_ERROR) {
106  _log(TCP_SERVER__ERROR, "Open()::listen() failed, Error: %s", strerror( errno ) );
107  if (errbuf)
108  snprintf( errbuf, TCPSRV_ERRBUF_SIZE, "%s", strerror( errno ) );
109  SafeDelete( mSock );
110  return false;
111  }
112 
113  mPort = port;
114  StartLoop();
115  return true;
116 }
117 
119 {
120  MutexLock lock(mMSock);
121  SafeDelete(mSock);
122  mPort = 0;
123 }
124 
126 {
127  /* since there is only one instance of BaseTCPServer, we can create thread here instead
128  * of sending to Thread class for creation and management
129  * update this to use Thread class management (sThread) if management here becomes a problem.
130  */
131  sThread.CreateThread(TCPServerLoop, this);
132  /*
133  pthread_t thread;
134  pthread_create( &thread, nullptr, TCPServerLoop, this );
135  _log(THREAD__WARNING, "StartLoop() - Created thread ID 0x%X for TCPServerLoop", thread);
136  sThread.AddThread(thread);*/
137 }
138 
140 {
141  //wait for running loop to stop.
144 }
145 
147 {
148  MutexLock lock( mMSock );
149  if (IsOpen()) {
151  return true;
152  }
153  return false;
154 }
155 
157 {
158  Socket* sock(nullptr);
159  sockaddr_in from = sockaddr_in();
160  from.sin_family = AF_INET;
161  unsigned int fromlen = sizeof( from );
162  MutexLock lock( mMSock );
163 
164  while ((sock = mSock->accept((sockaddr*)&from, &fromlen))) {
165  sock->fcntl( F_SETFL, O_NONBLOCK );
166  unsigned int bufsize = 64 * 1024; // 64kbyte receive buffer, up from default of 8k
167  sock->setopt( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof( bufsize ) );
168  // New TCP connection, this must consume the socket.
169  CreateNewConnection( sock, from.sin_addr.s_addr, ntohs( from.sin_port ) );
170  }
171 }
172 
174 {
175  BaseTCPServer* tcps = reinterpret_cast< BaseTCPServer* >( arg );
176  assert( tcps != nullptr );
177 
178  tcps->TCPServerLoop();
179 
180  return nullptr;
181 }
182 
184 {
186  uint32 start = GetTickCount();
187  while (Process()) {
188  // do the stuff for thread sleeping
189  start = GetTickCount() - start;
190  if (TCPSRV_LOOP_GRANULARITY > start)
192  start = GetTickCount();
193  }
195 }
Simple wrapper for sockets.
Definition: Socket.h:34
#define _log(type, fmt,...)
Definition: logsys.h:124
int listen(int backlog=SOMAXCONN)
Definition: Socket.cpp:84
void WaitLoop()
Waits for worker thread to terminate.
Definition: TCPServer.cpp:139
void TCPServerLoop()
Loop for worker threads.
Definition: TCPServer.cpp:183
BaseTCPServer()
Creates empty TCP server.
Definition: TCPServer.cpp:37
A lock for a Lockable object.
Definition: Lock.h:70
Socket * mSock
Definition: TCPServer.h:122
Mutex mMSock
Definition: TCPServer.h:120
int bind(const sockaddr *name, unsigned int namelen)
Definition: Socket.cpp:79
void Lock()
Locks the mutex.
Definition: Mutex.cpp:57
const uint32 TCPSRV_LOOP_GRANULARITY
Definition: TCPServer.cpp:35
const uint32 TCPSRV_ERRBUF_SIZE
Definition: TCPServer.cpp:34
void SafeDelete(T *&p)
Deletes and nullifies a pointer.
Definition: SafeMem.h:83
#define sThread
Definition: Threading.h:50
void ListenNewConnections()
Accepts all new connections.
Definition: TCPServer.cpp:156
void Close()
Stops started listening.
Definition: TCPServer.cpp:118
#define snprintf
Definition: eve-compat.h:184
bool Open(uint16 port, char *errbuf=0)
Start listening on specified port.
Definition: TCPServer.cpp:61
virtual ~BaseTCPServer()
Cleans server up.
Definition: TCPServer.cpp:43
uint32 GetTickCount()
Definition: eve-compat.cpp:39
int setopt(int level, int optname, const void *optval, unsigned int optlen)
Definition: Socket.cpp:99
Mutex mMLoopRunning
Definition: TCPServer.h:127
void Unlock()
Unlocks the mutex.
Definition: Mutex.cpp:75
uint16 mPort
Definition: TCPServer.h:124
unsigned __int32 uint32
Definition: eve-compat.h:50
Socket * accept(sockaddr *addr, unsigned int *addrlen)
Definition: Socket.cpp:89
void Sleep(uint32 x)
Definition: eve-compat.cpp:32
virtual void CreateNewConnection(Socket *sock, uint32 rIP, uint16 rPort)=0
Processes new connection.
#define SOCKET_ERROR
Definition: eve-compat.h:130
int fcntl(int cmd, long arg)
Definition: Socket.cpp:104
void StartLoop()
Starts worker thread.
Definition: TCPServer.cpp:125
static void * TCPServerLoop(void *arg)
Loop for worker threads.
Definition: TCPServer.cpp:173
bool IsOpen() const
Definition: TCPServer.cpp:53
Generic class for TCP server.
Definition: TCPServer.h:42
unsigned __int16 uint16
Definition: eve-compat.h:48
virtual bool Process()
Does periodical stuff to keep the server alive.
Definition: TCPServer.cpp:146