* Merged do_sendrecv() and do_parse() into do_sockets()

* Fixed subnet check message displaying incorrect ip addresses
* client_addr will now be properly set to 0 for server connections
* Removed socket code that attempts to cope with code bugs at runtime
* Removed outdated copyright and version number from startup logo

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11503 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-10-17 20:24:48 +00:00
parent 05134f3dcc
commit 0bbf505d59
10 changed files with 141 additions and 154 deletions

View File

@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/10/17
* Removed outdated copyright and version number from startup logo
* Removed socket code that attempts to cope with code bugs at runtime
* client_addr will now be properly set to 0 for server connections
* Fixed subnet check message displaying incorrect ip addresses
* Merged do_sendrecv() and do_parse() into do_sockets() [ultramage]
* Reworked the parsing at npc.c.
- Fixes npc.c discarding the '}' at the end of file, when there is no
newline. (uncovered as a side-effect of r11487)

View File

@ -3745,12 +3745,13 @@ int parse_char(int fd)
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
session[fd]->func_parse = parse_frommap;
server_fd[i] = fd;
server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map));
session[fd]->func_parse = parse_frommap;
session[fd]->client_addr = 0;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd);
// send gm acccounts level to map-servers
@ -3951,6 +3952,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data)
return 0;
}
session[login_fd]->func_parse = parse_fromlogin;
session[login_fd]->client_addr = 0;
realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
WFIFOHEAD(login_fd,86);

View File

@ -3075,12 +3075,13 @@ int parse_char(int fd)
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
session[fd]->func_parse = parse_frommap;
server_fd[i] = fd;
server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map));
session[fd]->func_parse = parse_frommap;
session[fd]->client_addr = 0;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd);
// send gm acccounts level to map-servers
@ -3280,6 +3281,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data)
return 0;
}
session[login_fd]->func_parse = parse_fromlogin;
session[login_fd]->client_addr = 0;
realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
WFIFOHEAD(login_fd,86);

View File

@ -1,28 +1,27 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <signal.h>
#include <string.h>
#include "core.h"
#include "../common/mmo.h"
#include "../common/version.h"
#include "../common/showmsg.h"
#include "../common/malloc.h"
#include "core.h"
#ifndef MINICORE
#include "../common/db.h"
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/plugins.h"
#endif
#ifndef _WIN32
#include "svnversion.h"
#include "svnversion.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
int runflag = 1;
@ -32,7 +31,7 @@ char **arg_v = NULL;
char *SERVER_NAME = NULL;
char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef SVNVERSION
static char eA_svn_version[10];
static char eA_svn_version[10] = "";
#endif
#ifndef MINICORE // minimalist Core
@ -178,21 +177,21 @@ static void display_title(void)
{
//ClearScreen(); // clear screen and go up/left (0, 0 position in text)
ShowMessage("\n");
ShowMessage(""CL_WTBL" (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)"CL_CLL""CL_NORMAL"\n"); // white writing (37) on blue background (44), \033[K clean until end of file
ShowMessage(""CL_XXBL" ("CL_BT_YELLOW" (c)2005 eAthena Development Team presents "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // yellow writing (33)
ShowMessage(""CL_XXBL" ("CL_BOLD" ______ __ __ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d "CL_XXBL")"CL_CLL""CL_NORMAL"\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" /'__`\\ \\ __ \\ \\ \\/\\ \\ _ `\\ /'__`\\/' _ `\\ /'__`\\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" /\\ __/\\ \\ \\/\\ \\ \\ \\_\\ \\ \\ \\ \\/\\ __//\\ \\/\\ \\/\\ \\_\\.\\_ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" \\ \\____\\\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\____\\ \\_\\ \\_\\ \\__/.\\_\\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" \\/____/ \\/_/\\/_/\\/__/ \\/_/\\/_/\\/____/\\/_/\\/_/\\/__/\\/_/ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" _ _ _ _ _ _ _ _ _ _ _ _ _ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // 1: bold char, 0: normal char
ShowMessage(""CL_XXBL" ("CL_BOLD" "CL_XXBL")"CL_CLL""CL_NORMAL"\n"); // yellow writing (33)
ShowMessage(""CL_WTBL" (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)"CL_CLL""CL_NORMAL"\n\n"); // reset color
ShowMessage(""CL_WTBL" (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BT_YELLOW" eAthena Development Team presents "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" ______ __ __ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" /\\ _ \\/\\ \\__/\\ \\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" /'__`\\ \\ __ \\ \\ \\/\\ \\ _ `\\ /'__`\\/' _ `\\ /'__`\\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" /\\ __/\\ \\ \\/\\ \\ \\ \\_\\ \\ \\ \\ \\/\\ __//\\ \\/\\ \\/\\ \\_\\.\\_ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" \\ \\____\\\\ \\_\\ \\_\\ \\__\\\\ \\_\\ \\_\\ \\____\\ \\_\\ \\_\\ \\__/.\\_\\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" \\/____/ \\/_/\\/_/\\/__/ \\/_/\\/_/\\/____/\\/_/\\/_/\\/__/\\/_/ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" _ _ _ _ _ _ _ _ _ _ _ _ _ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ / \\ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_XXBL" ("CL_BOLD" "CL_XXBL")"CL_CLL""CL_NORMAL"\n");
ShowMessage(""CL_WTBL" (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)"CL_CLL""CL_NORMAL"\n\n");
ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'.\n", get_svn_revision());
}
@ -224,9 +223,6 @@ int main (int argc, char **argv)
}
arg_c = argc;
arg_v = argv;
#ifndef SVNVERSION
*eA_svn_version = '\0';
#endif
}
malloc_init();// needed for Show* in display_title() [FlavioJS]
@ -255,8 +251,7 @@ int main (int argc, char **argv)
int next;
while (runflag) {
next = do_timer(gettick_nocache());
do_sendrecv(next);
do_parsepacket();
do_sockets(next);
}
}

View File

@ -41,6 +41,7 @@
#define s_errno WSAGetLastError()
#define S_ENOTSOCK WSAENOTSOCK
#define S_EWOULDBLOCK WSAEWOULDBLOCK
#define S_EINTR WSAEINTR
#define S_ECONNABORTED WSAECONNABORTED
#define SHUT_RD SD_RECEIVE
@ -55,6 +56,7 @@
#define s_errno errno
#define S_ENOTSOCK EBADF
#define S_EWOULDBLOCK EAGAIN
#define S_EINTR EINTR
#define S_ECONNABORTED ECONNABORTED
#endif
@ -66,13 +68,11 @@ time_t stall_time = 60;
uint32 addr_[16]; // ip addresses of local host (host byte order)
int naddr_ = 0; // # of ip addresses
#define MODE_NODELAY 1 // disables|enables packet buffering
// values derived from freya
// a player that send more than 2k is probably a hacker without be parsed
// initial recv buffer size (this will also be the max. size)
// biggest known packet: S 0153 <len>.w <emblem data>.?B -> 24x24 256 color .bmp (0153 + len.w + 1618/1654/1756 bytes)
size_t rfifo_size = (16*1024);
size_t wfifo_size = (16*1024);
#define RFIFO_SIZE (2*1024)
// initial send buffer size (will be resized as needed)
#define WFIFO_SIZE (16*1024)
struct socket_data* session[FD_SETSIZE];
@ -82,7 +82,7 @@ int send_shortlist_count = 0;// how many fd's are in the shortlist
fd_set send_shortlist_fd_set;// to know if specific fd's are already in the shortlist
#endif
int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse);
static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse);
#ifndef MINICORE
int ip_rules = 1;
@ -110,11 +110,6 @@ void set_defaultparse(ParseFunc defaultparse)
*--------------------------------------*/
void set_nonblocking(int fd, unsigned long yes)
{
// TCP_NODELAY BOOL Disables the Nagle algorithm for send coalescing.
#if defined(MODE_NODELAY) && MODE_NODELAY == 1
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof yes);
#endif
// FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s.
// The argp parameter is zero if nonblocking is to be disabled.
if (ioctlsocket(fd, FIONBIO, &yes) != 0)
@ -133,9 +128,10 @@ void setsocketopts(int fd)
setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof(yes));
#endif
#endif
// Set the socket into no-delay mode; otherwise packets get delayed for up to 200ms, likely creating server-side lag.
// The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
// setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &wfifo_size , sizeof(rfifo_size ));
// setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rfifo_size , sizeof(rfifo_size ));
// 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)
@ -172,19 +168,17 @@ int recv_to_fifo(int fd)
len = recv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);
if (len == SOCKET_ERROR) {
if (s_errno == S_ECONNABORTED) {
ShowWarning("recv_to_fifo: Software caused connection abort on session #%d\n", fd);
FD_CLR(fd, &readfds); //Remove the socket so the select() won't hang on it.
}
if (s_errno != S_EWOULDBLOCK) {
//ShowDebug("recv_to_fifo: error %d, ending connection #%d\n", s_errno, fd);
if( len == SOCKET_ERROR )
{//An exception has occured
if( s_errno != S_EWOULDBLOCK ) {
ShowDebug("recv_to_fifo: code %d, closing connection #%d\n", s_errno, fd);
set_eof(fd);
}
return 0;
}
if (len == 0) { //Normal connection end.
if( len == 0 )
{//Normal connection end.
set_eof(fd);
return 0;
}
@ -201,27 +195,28 @@ int send_from_fifo(int fd)
if( !session_isValid(fd) )
return -1;
if (session[fd]->wdata_size == 0)
return 0;
if( session[fd]->wdata_size == 0 )
return 0; // nothing to send
ShowInfo("Session #%d sending %d bytes.\n", fd, session[fd]->wdata_size);
len = send(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, 0);
if (len == SOCKET_ERROR) {
if (s_errno == S_ECONNABORTED) {
ShowWarning("send_from_fifo: Software caused connection abort on session #%d\n", fd);
FD_CLR(fd, &readfds); //Remove the socket so the select() won't hang on it.
}
if (s_errno != S_EWOULDBLOCK) {
//ShowDebug("send_from_fifo: error %d, ending connection #%d\n", s_errno, fd);
if( len == SOCKET_ERROR )
{
if( s_errno != S_EWOULDBLOCK ) {
ShowDebug("send_from_fifo: error %d, ending connection #%d\n", s_errno, fd);
session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
set_eof(fd);
}
return 0;
}
//{ int i; ShowMessage("send %d : ",fd); for(i=0;i<len;i++){ ShowMessage("%02x ",session[fd]->wdata[i]); } ShowMessage("\n");}
if(len > 0) {
if((size_t)len < session[fd]->wdata_size)
// some data could not be transferred?
if( len > 0 )
{
// shift unsent data to the beginning of the queue
if( (size_t)len < session[fd]->wdata_size )
memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);
session[fd]->wdata_size -= len;
@ -282,7 +277,6 @@ int connect_client(int listen_fd)
create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
session[fd]->rdata_tick = last_tick;
return fd;
}
@ -333,6 +327,8 @@ int make_listen_bind(uint32 ip, uint16 port)
FD_SET(fd, &readfds);
create_session(fd, connect_client, null_send, null_parse);
session[fd]->rdata_tick = 0; // disable timeouts on this socket
session[fd]->client_addr = 0;
return fd;
}
@ -377,25 +373,26 @@ int make_connection(uint32 ip, uint16 port)
FD_SET(fd,&readfds);
create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
session[fd]->rdata_tick = last_tick;
session[fd]->client_addr = 0;
return fd;
}
int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse)
static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseFunc func_parse)
{
CREATE(session[fd], struct socket_data, 1);
CREATE(session[fd]->rdata, unsigned char, rfifo_size);
CREATE(session[fd]->wdata, unsigned char, wfifo_size);
session[fd]->max_rdata = rfifo_size;
session[fd]->max_wdata = wfifo_size;
CREATE(session[fd]->rdata, unsigned char, RFIFO_SIZE);
CREATE(session[fd]->wdata, unsigned char, WFIFO_SIZE);
session[fd]->max_rdata = RFIFO_SIZE;
session[fd]->max_wdata = WFIFO_SIZE;
session[fd]->func_recv = func_recv;
session[fd]->func_send = func_send;
session[fd]->func_parse = func_parse;
session[fd]->rdata_tick = last_tick;
return 0;
}
int delete_session(int fd)
static int delete_session(int fd)
{
if (fd <= 0 || fd >= FD_SETSIZE)
return -1;
@ -435,29 +432,45 @@ int realloc_writefifo(int fd, size_t addition)
return 0;
if( session[fd]->wdata_size + addition > session[fd]->max_wdata )
{ // grow rule; grow in multiples of wfifo_size
newsize = wfifo_size;
{ // grow rule; grow in multiples of WFIFO_SIZE
newsize = WFIFO_SIZE;
while( session[fd]->wdata_size + addition > newsize ) newsize += newsize;
}
else if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK) {
else
if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK)
{
//Inter-server adjust. [Skotlex]
if ((session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata)
newsize = session[fd]->max_wdata / 2;
else
return 0; //No change
} else if( session[fd]->max_wdata > wfifo_size && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
}
else
if( session[fd]->max_wdata > WFIFO_SIZE && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
{ // shrink rule, shrink by 2 when only a quater of the fifo is used, don't shrink below 4*addition
newsize = session[fd]->max_wdata / 2;
}
else // no change
return 0;
// crash prevention for bugs that cause the send queue to fill up in an infinite loop
if( newsize > 1*1024*1024 ) // 1 megabyte is way beyond reasonable
{
ShowError("realloc_writefifo: session #%d's send buffer was overloaded! Disconnecting...\n", fd);
// drop all data (but the space will still be available)
session[fd]->wdata_size = 0;
// request disconnect
set_eof(fd);
return 0;
}
RECREATE(session[fd]->wdata, unsigned char, newsize);
session[fd]->max_wdata = newsize;
return 0;
}
/// advance the RFIFO cursor (marking 'len' bytes as processed)
int RFIFOSKIP(int fd, size_t len)
{
struct socket_data *s;
@ -468,16 +481,15 @@ int RFIFOSKIP(int fd, size_t len)
s = session[fd];
if ( s->rdata_size < s->rdata_pos + len ) {
//fprintf(stderr,"too many skip\n");
//exit(EXIT_FAILURE);
//better than a COMPLETE program abort // TEST! :)
ShowError("too many skip (%d) now skipped: %d (FD: %d)\n", len, RFIFOREST(fd), fd);
ShowError("RFIFOSKIP: skipped past end of read buffer! Adjusting from %d to %d (session #%d)\n", len, RFIFOREST(fd), fd);
len = RFIFOREST(fd);
}
s->rdata_pos = s->rdata_pos + len;
return 0;
}
/// advance the WFIFO cursor (marking 'len' bytes for sending)
int WFIFOSET(int fd, size_t len)
{
size_t newreserve;
@ -490,20 +502,18 @@ int WFIFOSET(int fd, size_t len)
if(s->wdata_size+len > s->max_wdata)
{ // actually there was a buffer overflow already
uint32 ip = s->client_addr;
ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n",
fd, CONVIP(ip), len, s->wdata_size, s->max_wdata);
ShowFatalError("WFIFOSET: Write Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd, CONVIP(ip), len, s->wdata_size, s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata + s->wdata_size)));
// no other chance, make a better fifo model
exit(EXIT_FAILURE);
}
s->wdata_size += len;
// always keep a wfifo_size reserve in the buffer
// always keep a WFIFO_SIZE reserve in the buffer
// For inter-server connections, let the reserve be 1/4th of the link size.
newreserve = s->wdata_size + (s->max_wdata >= FIFOSIZE_SERVERLINK ? FIFOSIZE_SERVERLINK / 4 : wfifo_size);
newreserve = s->wdata_size + (s->max_wdata >= FIFOSIZE_SERVERLINK ? FIFOSIZE_SERVERLINK / 4 : WFIFO_SIZE);
// readfifo does not need to be realloced at all
// Even the inter-server buffer may need reallocating! [Skotlex]
// readjust the buffer to the newly chosen size
realloc_writefifo(fd, newreserve);
#ifdef SEND_SHORTLIST
@ -513,17 +523,16 @@ int WFIFOSET(int fd, size_t len)
return 0;
}
int do_sendrecv(int next)
int do_sockets(int next)
{
fd_set rfd;
struct sockaddr_in addr_check;
struct timeval timeout;
int ret,i,size;
int ret,i;
last_tick = time(0);
// PRESEND Timers are executed before do_sendrecv and can send packets
// and/or set sessions to eof. Send remaining data and handle eof sessions.
// PRESEND Timers are executed before do_sendrecv and can send packets and/or set sessions to eof.
// Send remaining data and process client-side disconnects here.
#ifdef SEND_SHORTLIST
send_shortlist_do_sends();
#else
@ -541,45 +550,17 @@ int do_sendrecv(int next)
timeout.tv_sec = next/1000;
timeout.tv_usec = next%1000*1000;
for(memcpy(&rfd, &readfds, sizeof(rfd));
(ret = select(fd_max, &rfd, NULL, NULL, &timeout))<0;
memcpy(&rfd, &readfds, sizeof(rfd)))
memcpy(&rfd, &readfds, sizeof(rfd));
ret = select(fd_max, &rfd, NULL, NULL, &timeout);
if( ret < 0 )
{
if(s_errno != S_ENOTSOCK)
return 0;
//Well then the error is due to a bad socket. Lets find and remove it
//and try again
for(i = 1; i < fd_max; i++)
if( ret != S_EINTR )
{
if(!session[i])
{
if (FD_ISSET(i, &readfds)) {
ShowError("Deleting non-cleared session %d\n", i);
FD_CLR(i, &readfds);
}
continue;
}
//check the validity of the socket. Does what the last thing did
//just alot faster [Meruru]
size = sizeof(struct sockaddr);
if(getsockname(i,(struct sockaddr*)&addr_check,&size)<0)
if(s_errno == S_ENOTSOCK)
{
ShowError("Deleting invalid session %d\n", i);
//So the code can react accordingly
set_eof(i);
session[i]->func_parse(i);
delete_session(i); //free the bad session
continue;
}
if (!FD_ISSET(i, &readfds))
FD_SET(i,&readfds);
ret = i;
ShowFatalError("do_sockets: select() returned %d!\n", ret);
exit(EXIT_FAILURE);
}
fd_max = ret;
return 0;
}
#ifdef WIN32
@ -618,12 +599,7 @@ int do_sendrecv(int next)
}
#endif
return 0;
}
int do_parsepacket(void)
{
int i;
// parse input data on each socket
for(i = 1; i < fd_max; i++)
{
if(!session[i])
@ -639,13 +615,14 @@ int do_parsepacket(void)
if(!session[i])
continue;
/* 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 == rfifo_size && session[i]->max_rdata == rfifo_size) {
// 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 == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) {
set_eof(i);
continue;
}
RFIFOFLUSH(i);
}
return 0;
}
@ -1120,12 +1097,12 @@ void socket_init(void)
}
int session_isValid(int fd)
bool session_isValid(int fd)
{
return ( (fd > 0) && (fd < FD_SETSIZE) && (session[fd] != NULL) );
return ( fd > 0 && fd < FD_SETSIZE && session[fd] != NULL );
}
int session_isActive(int fd)
bool session_isActive(int fd)
{
return ( session_isValid(fd) && !session[fd]->eof );
}

View File

@ -68,18 +68,23 @@ typedef int (*RecvFunc)(int fd);
typedef int (*SendFunc)(int fd);
typedef int (*ParseFunc)(int fd);
struct socket_data {
struct socket_data
{
unsigned char eof;
unsigned char *rdata, *wdata;
size_t max_rdata, max_wdata;
size_t rdata_size, wdata_size;
size_t rdata_pos;
time_t rdata_tick; // time of last receive (for detecting timeouts)
uint32 client_addr; // remote client address (zero for s2s connections)
void* session_data;
time_t rdata_tick; // time of last recv (for detecting timeouts); zero when timeout is disabled
uint32 client_addr; // remote client address (0 for server connections)
RecvFunc func_recv;
SendFunc func_send;
ParseFunc func_parse;
void* session_data; // stores application-specific data related to the session
};
@ -94,8 +99,8 @@ extern time_t stall_time;
//////////////////////////////////
// some checking on sockets
extern int session_isValid(int fd);
extern int session_isActive(int fd);
extern bool session_isValid(int fd);
extern bool session_isActive(int fd);
//////////////////////////////////
// Function prototype declaration
@ -107,8 +112,7 @@ int realloc_writefifo(int fd, size_t addition);
int WFIFOSET(int fd, size_t len);
int RFIFOSKIP(int fd, size_t len);
int do_sendrecv(int next);
int do_parsepacket(void);
int do_sockets(int next);
void do_close(int fd);
void socket_init(void);
void socket_final(void);
@ -123,7 +127,7 @@ void set_defaultparse(ParseFunc defaultparse);
uint32 host2ip(const char* hostname);
const char* ip2str(uint32 ip, char ip_str[16]);
uint32 str2ip(const char* ip_str);
#define CONVIP(ip) (ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,(ip>>0)&0xFF
#define CONVIP(ip) ((ip)>>24)&0xFF,((ip)>>16)&0xFF,((ip)>>8)&0xFF,((ip)>>0)&0xFF
uint16 ntows(uint16 netshort);
int socket_getips(uint32* ips, int max);

View File

@ -3248,7 +3248,7 @@ int parse_fromlogin(int fd)
ladmin_log("Impossible to have a connection with the login-server [%s:%d] !\n", loginserverip, loginserverport);
}
do_close(fd);
exit (0);
exit(EXIT_FAILURE);
}
// ShowMessage("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
@ -4384,8 +4384,7 @@ int do_init(int argc, char **argv)
// so we have to do this ourselves
while (runflag) {
next = do_timer(gettick_nocache());
do_sendrecv(next);
do_parsepacket();
do_sockets(next);
}
return 0;

View File

@ -3194,6 +3194,7 @@ int parse_login(int fd)
WFIFOSET(fd,3);
session[fd]->func_parse = parse_fromchar;
session[fd]->client_addr = 0;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
send_GM_accounts(fd); // send GM account to char-server

View File

@ -1538,6 +1538,7 @@ int parse_login(int fd)
WFIFOSET(fd,3);
session[fd]->func_parse = parse_fromchar;
session[fd]->client_addr = 0;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
send_GM_accounts(fd); // send GM account to char-server

View File

@ -1386,6 +1386,7 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data)
}
session[char_fd]->func_parse = chrif_parse;
session[char_fd]->client_addr = 0;
realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
chrif_connect(char_fd);