summaryrefslogtreecommitdiff
path: root/src/common/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/socket.c')
-rw-r--r--src/common/socket.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/src/common/socket.c b/src/common/socket.c
index 0c48c7c46..09521c312 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -29,8 +29,12 @@
# include <errno.h>
# include <net/if.h>
# include <netdb.h>
+#if defined __linux__ || defined __linux
+# include <linux/tcp.h>
+#else
# include <netinet/in.h>
# include <netinet/tcp.h>
+#endif
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/time.h>
@@ -274,7 +278,7 @@ const char* error_msg(void)
}
/*======================================
- * CORE : Default processing functions
+ * CORE : Default processing functions
*--------------------------------------*/
int null_recv(int fd) { return 0; }
int null_send(int fd) { return 0; }
@@ -289,7 +293,7 @@ void set_defaultparse(ParseFunc defaultparse)
/*======================================
- * CORE : Socket options
+ * CORE : Socket options
*--------------------------------------*/
void set_nonblocking(int fd, unsigned long yes)
{
@@ -302,7 +306,7 @@ void set_nonblocking(int fd, unsigned long yes)
void setsocketopts(int fd, struct hSockOpt *opt) {
int yes = 1; // reuse fix
struct linger lopt;
-
+
#if !defined(WIN32)
// set SO_REAUSEADDR to true, unix only. on windows this option causes
// the previous owner of the socket to give up, which is not desirable
@@ -319,24 +323,31 @@ void setsocketopts(int fd, struct hSockOpt *opt) {
if( opt && opt->setTimeo ) {
struct timeval timeout;
-
+
timeout.tv_sec = 5;
timeout.tv_usec = 0;
-
+
sSetsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
sSetsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
}
-
+
// force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
//(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
lopt.l_onoff = 0; // SO_DONTLINGER
lopt.l_linger = 0; // Do not care
if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lopt, sizeof(lopt)) )
ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
+
+#ifdef TCP_THIN_LINEAR_TIMEOUTS
+ setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof yes);
+#endif
+#ifdef TCP_THIN_DUPACK
+ setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes);
+#endif
}
/*======================================
- * CORE : Socket Sub Function
+ * CORE : Socket Sub Function
*--------------------------------------*/
void set_eof(int fd)
{
@@ -448,7 +459,7 @@ void flush_fifos(void)
}
/*======================================
- * CORE : Connection functions
+ * CORE : Connection functions
*--------------------------------------*/
int connect_client(int listen_fd) {
int fd;
@@ -659,19 +670,19 @@ int realloc_writefifo(int fd, size_t addition)
if( !sockt->session_isValid(fd) ) // might not happen
return 0;
- if( session[fd]->wdata_size + addition > session[fd]->max_wdata )
- { // grow rule; grow in multiples of WFIFO_SIZE
+ if (session[fd]->wdata_size + addition > session[fd]->max_wdata) {
+ // grow rule; grow in multiples of WFIFO_SIZE
newsize = WFIFO_SIZE;
while( session[fd]->wdata_size + addition > newsize ) newsize += WFIFO_SIZE;
- }
- else
- if( session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
- && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
- { // shrink rule, shrink by 2 when only a quarter of the fifo is used, don't shrink below nominal size.
+ } else if (session[fd]->max_wdata >= (size_t)2*(session[fd]->flag.server?FIFOSIZE_SERVERLINK:WFIFO_SIZE)
+ && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata
+ ) {
+ // shrink rule, shrink by 2 when only a quarter of the fifo is used, don't shrink below nominal size.
newsize = session[fd]->max_wdata / 2;
- }
- else // no change
+ } else {
+ // no change
return 0;
+ }
RECREATE(session[fd]->wdata, unsigned char, newsize);
session[fd]->max_wdata = newsize;
@@ -682,7 +693,7 @@ int realloc_writefifo(int fd, size_t addition)
/// advance the RFIFO cursor (marking 'len' bytes as processed)
int RFIFOSKIP(int fd, size_t len)
{
- struct socket_data *s;
+ struct socket_data *s;
if ( !sockt->session_isActive(fd) )
return 0;
@@ -711,8 +722,8 @@ int WFIFOSET(int fd, size_t len)
return 0;
// we have written len bytes to the buffer already before calling WFIFOSET
- if(s->wdata_size+len > s->max_wdata)
- { // actually there was a buffer overflow already
+ if (s->wdata_size+len > s->max_wdata) {
+ // actually there was a buffer overflow already
uint32 ip = s->client_addr;
ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %u bytes on a %u/%u bytes buffer.\n", fd, CONVIP(ip), (unsigned int)len, (unsigned int)s->wdata_size, (unsigned int)s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", (*(uint16*)(s->wdata + s->wdata_size)));
@@ -744,13 +755,6 @@ int WFIFOSET(int fd, size_t len)
return 0;
}
- if (s->wdata_size+len > WFIFO_MAX) { // reached maximum write fifo size
- ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%"PRIuS", ip=%u.%u.%u.%u).\n",
- fd, WFIFOW(fd,0), len, CONVIP(s->client_addr));
- set_eof(fd);
- return 0;
- }
-
}
s->wdata_size += len;
#ifdef SHOW_SERVER_STATS
@@ -846,8 +850,8 @@ int do_sockets(int next)
if(session[i]->wdata_size)
session[i]->func_send(i);
- if(session[i]->flag.eof) //func_send can't free a session, this is safe.
- { //Finally, even if there is no data to parse, connections signaled eof should be closed, so we call parse_func [Skotlex]
+ if (session[i]->flag.eof) { //func_send can't free a session, this is safe.
+ //Finally, even if there is no data to parse, connections signaled eof should be closed, so we call parse_func [Skotlex]
session[i]->func_parse(i); //This should close the session immediately.
}
}
@@ -877,7 +881,7 @@ int do_sockets(int next)
if(!session[i])
continue;
-
+
RFIFOFLUSH(i);
// after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed)
if (session[i]->rdata_size == session[i]->max_rdata) {
@@ -890,7 +894,7 @@ int do_sockets(int next)
if (sockt->last_tick != socket_data_last_tick)
{
char buf[1024];
-
+
sprintf(buf, "In: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | Out: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | RAM: %.03f MB", socket_data_i/1024., socket_data_ci/1024., socket_data_qi/1024., socket_data_o/1024., socket_data_co/1024., socket_data_qo/1024., iMalloc->usage()/1024.);
#ifdef _WIN32
SetConsoleTitle(buf);
@@ -1239,7 +1243,7 @@ void socket_final(void)
aFree(session[0]->rdata);
aFree(session[0]->wdata);
aFree(session[0]);
-
+
aFree(session);
}
@@ -1403,7 +1407,7 @@ void socket_init(void)
#endif
CREATE(session, struct socket_data *, FD_SETSIZE);
-
+
socket_config_read(SOCKET_CONF_FILENAME);
// initialize last send-receive tick
@@ -1421,7 +1425,7 @@ void socket_init(void)
#endif
ShowInfo("Server supports up to '"CL_WHITE"%"PRId64""CL_RESET"' concurrent connections.\n", rlim_cur);
-
+
/* Hercules Plugin Manager */
HPM->share(session,"session");
}
@@ -1505,11 +1509,11 @@ void socket_datasync(int fd, bool send) {
WFIFOW(fd, 0) = 0x2b0a;
WFIFOW(fd, 2) = p_len;
-
+
for( i = 0; i < alen; i++ ) {
WFIFOL(fd, 4 + ( i * 4 ) ) = data_list[i].length;
}
-
+
WFIFOSET(fd, p_len);
} else {
for( i = 0; i < alen; i++ ) {
@@ -1609,7 +1613,7 @@ void send_shortlist_do_sends()
void socket_defaults(void) {
sockt = &sockt_s;
-
+
sockt->fd_max = 0;
/* */
sockt->stall_time = 60;