summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorDennis Friis <peavey@inspircd.org>2009-07-07 00:52:08 +0200
committerDennis Friis <peavey@inspircd.org>2009-07-07 00:55:31 +0200
commit4673fd3ca06010e74f8223486b0f34e58c7b0a7e (patch)
treecfcc97752fd770eb1befa295e16f7aa4a2607ca9 /src/common
parent03b5e644857f80a23bd8b856b78a10cf0a564a66 (diff)
downloadtmwa-4673fd3ca06010e74f8223486b0f34e58c7b0a7e.tar.gz
tmwa-4673fd3ca06010e74f8223486b0f34e58c7b0a7e.tar.bz2
tmwa-4673fd3ca06010e74f8223486b0f34e58c7b0a7e.tar.xz
tmwa-4673fd3ca06010e74f8223486b0f34e58c7b0a7e.zip
Fixes to socket system to make it cope better with fd depletion.
Also added timeout for fullconnect, secured map server from stateless connections.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/grfio.c39
-rw-r--r--src/common/lock.c7
-rw-r--r--src/common/socket.c65
-rw-r--r--src/common/socket.h16
4 files changed, 104 insertions, 23 deletions
diff --git a/src/common/grfio.c b/src/common/grfio.c
index 08a8b2a..b5f380c 100644
--- a/src/common/grfio.c
+++ b/src/common/grfio.c
@@ -30,6 +30,7 @@
#include "utils.h"
#include "grfio.h"
#include "mmo.h"
+#include "socket.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -414,7 +415,7 @@ char* grfio_resnametable(char* fname, char *lfname)
for(p=&restable[0];*p!=0;p++) if (*p=='\\') *p = '/';
- fp = fopen(restable,"rb");
+ fp = fopen_(restable,"rb");
if(fp==NULL) {
printf("%s not found\n",restable);
exit(1); // 1:not found error
@@ -423,11 +424,11 @@ char* grfio_resnametable(char* fname, char *lfname)
while(fgets(line,508,fp)){
if((sscanf(line,"%[^#]#%[^#]#",w1,w2)==2) && (sscanf(fname,"%*5s%s",lfname)==1) && (!strcmpi(w1,lfname))){
sprintf(lfname,"data\\%s",w2);
- fclose(fp);
+ fclose_(fp);
return lfname;
}
}
- fclose(fp);
+ fclose_(fp);
return fname;
}
@@ -493,7 +494,7 @@ void* grfio_reads(char *fname, int *size)
for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix
- in = fopen(lfname,"rb");
+ in = fopen_(lfname,"rb");
if(in!=NULL) {
if (entry!=NULL && entry->gentry==0) {
lentry.declen=entry->declen;
@@ -508,7 +509,7 @@ void* grfio_reads(char *fname, int *size)
goto errret;
}
fread(buf2,1,lentry.declen,in);
- fclose(in); in = NULL;
+ fclose_(in); in = NULL;
strncpy( lentry.fn, fname, sizeof(lentry.fn)-1 );
lentry.gentry = 0; // 0:LocalFile
entry = filelist_modify(&lentry);
@@ -530,7 +531,7 @@ void* grfio_reads(char *fname, int *size)
goto errret;
}
gfname = gentry_table[entry->gentry-1];
- in = fopen(gfname,"rb");
+ in = fopen_(gfname,"rb");
if(in==NULL) {
printf("%s not found\n",gfname);
//goto errret;
@@ -539,7 +540,7 @@ void* grfio_reads(char *fname, int *size)
}
fseek(in,entry->srcpos,0);
fread(buf,1,entry->srclen_aligned,in);
- fclose(in);
+ fclose_(in);
buf2=calloc(entry->declen+1024, 1);
if (buf2==NULL) {
printf("file decode memory allocate error\n");
@@ -567,7 +568,7 @@ void* grfio_reads(char *fname, int *size)
errret:
if (buf!=NULL) free(buf);
if (buf2!=NULL) free(buf2);
- if (in!=NULL) fclose(in);
+ if (in!=NULL) fclose_(in);
exit(1); //return NULL;
}
@@ -609,7 +610,7 @@ static int grfio_entryread(char *gfname,int gentry)
unsigned char *fname;
unsigned char *grf_filelist;
- fp = fopen(gfname,"rb");
+ fp = fopen_(gfname,"rb");
if(fp==NULL) {
printf("%s not found\n",gfname);
return 1; // 1:not found error
@@ -620,7 +621,7 @@ static int grfio_entryread(char *gfname,int gentry)
fseek(fp,0,0); // SEEK_SET
fread(grf_header,1,0x2e,fp);
if(strcmp(grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){ // SEEK_CUR
- fclose(fp);
+ fclose_(fp);
printf("%s read error\n",gfname);
return 2; // 2:file format error
}
@@ -631,12 +632,12 @@ static int grfio_entryread(char *gfname,int gentry)
list_size = grf_size-ftell(fp);
grf_filelist = calloc(list_size, 1);
if(grf_filelist==NULL){
- fclose(fp);
+ fclose_(fp);
printf("out of memory : grf_filelist\n");
return 3; // 3:memory alloc error
}
fread(grf_filelist,1,list_size,fp);
- fclose(fp);
+ fclose_(fp);
entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7;
@@ -699,26 +700,26 @@ static int grfio_entryread(char *gfname,int gentry)
eSize = getlong(eheader+4); // Extend Size
if (rSize > grf_size-ftell(fp)) {
- fclose(fp);
+ fclose_(fp);
printf("Illegal data format : grf compress entry size\n");
return 4;
}
rBuf = calloc( rSize , 1); // Get a Read Size
if (rBuf==NULL) {
- fclose(fp);
+ fclose_(fp);
printf("out of memory : grf compress entry table buffer\n");
return 3;
}
grf_filelist = calloc( eSize , 1); // Get a Extend Size
if (grf_filelist==NULL) {
free(rBuf);
- fclose(fp);
+ fclose_(fp);
printf("out of memory : grf extract entry table buffer\n");
return 3;
}
fread(rBuf,1,rSize,fp);
- fclose(fp);
+ fclose_(fp);
decode_zip(grf_filelist,&eSize,rBuf,rSize); // Decode function
list_size = eSize;
free(rBuf);
@@ -767,7 +768,7 @@ static int grfio_entryread(char *gfname,int gentry)
free(grf_filelist);
} else { //****** Grf Other version ******
- fclose(fp);
+ fclose_(fp);
printf("not support grf versions : %04x\n",getlong(grf_header+0x2a));
return 4;
}
@@ -903,7 +904,7 @@ void grfio_init(char *fname)
char line[1024], w1[1024], w2[1024];
int result = 0, result2 = 0, result3 = 0;
- data_conf = fopen(fname, "r");
+ data_conf = fopen_(fname, "r");
// It will read, if there is grf-files.txt.
if (data_conf) {
@@ -920,7 +921,7 @@ void grfio_init(char *fname)
}
}
- fclose(data_conf);
+ fclose_(data_conf);
printf("read %s done\n",fname);
} // end of reading grf-files.txt
diff --git a/src/common/lock.c b/src/common/lock.c
index 9a2205b..67001f9 100644
--- a/src/common/lock.c
+++ b/src/common/lock.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include "lock.h"
+#include "socket.h"
// 書き込みファイルの保護処理
// (書き込みが終わるまで、旧ファイルを保管しておく)
@@ -14,9 +15,9 @@ FILE* lock_fopen(const char* filename,int *info) {
// 安全なファイル名を得る(手抜き)
do {
sprintf(newfile,"%s_%04d.tmp",filename,++no);
- } while((fp = fopen(newfile,"r")) && (fclose(fp), no<9999) );
+ } while((fp = fopen_(newfile,"r")) && (fclose_(fp), no<9999) );
*info = no;
- return fopen(newfile,"w");
+ return fopen_(newfile,"w");
}
// 旧ファイルを削除&新ファイルをリネーム
@@ -24,7 +25,7 @@ int lock_fclose(FILE *fp,const char* filename,int *info) {
int ret = 0;
char newfile[512];
if(fp != NULL) {
- ret = fclose(fp);
+ ret = fclose_(fp);
sprintf(newfile,"%s_%04d.tmp",filename,*info);
remove(filename);
// このタイミングで落ちると最悪。
diff --git a/src/common/socket.c b/src/common/socket.c
index f968373..886072e 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <errno.h>
#ifdef LCCWIN32
#define WIN32_LEAN_AND_MEAN
@@ -30,6 +31,7 @@
fd_set readfds;
int fd_max;
+int currentuse;
int rfifo_size = 65536;
int wfifo_size = 65536;
@@ -74,6 +76,7 @@ static int recv_to_fifo(int fd)
//{ int i; printf("recv %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",RFIFOB(fd,session[fd]->rdata_size+i)); } printf("\n");}
if(len>0){
session[fd]->rdata_size+=len;
+ if (!session[fd]->connected) session[fd]->connected = 1;
} else if(len<=0){
// value of connection is not necessary the same
// if (fd == 4) // Removed [Yor]
@@ -117,6 +120,7 @@ static int send_from_fifo(int fd)
} else {
session[fd]->wdata_size=0;
}
+ if (!session[fd]->connected) session[fd]->connected = 1;
} else {
printf("set eof :%d\n",fd);
session[fd]->eof=1;
@@ -146,6 +150,8 @@ static int connect_client(int listen_fd)
//printf("connect_client : %d\n",listen_fd);
+ printf("used: %d, max FDs: %d, SOFT: %d\n", currentuse, FD_SETSIZE, SOFT_LIMIT);
+
len = sizeof(client_address);
fd = accept(listen_fd,(struct sockaddr*)&client_address,&len);
@@ -155,6 +161,11 @@ static int connect_client(int listen_fd)
perror("accept");
return -1;
}
+ if (!free_fds()) { // gracefully end the connecting if no free FD
+ printf("softlimit reached, disconnecting : %d\n", fd);
+ delete_session(fd);
+ return -1;
+ }
// setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,NULL,0);
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); // reuse fix
@@ -186,6 +197,10 @@ static int connect_client(int listen_fd)
session[fd]->func_send = send_from_fifo;
session[fd]->func_parse = default_func_parse;
session[fd]->client_addr = client_address;
+ session[fd]->created = time(NULL);
+ session[fd]->connected = 0;
+
+ currentuse++;
//printf("new_session : %d %d\n",fd,session[fd]->eof);
return fd;
@@ -200,6 +215,10 @@ int make_listen_port(int port)
fd = socket( AF_INET, SOCK_STREAM, 0 );
if(fd_max<=fd) fd_max=fd+1;
+ else if (fd == -1) {
+ perror("connect");
+ return -1;
+ }
#ifdef LCCWIN32
{
@@ -244,7 +263,10 @@ int make_listen_port(int port)
}
memset(session[fd],0,sizeof(*session[fd]));
session[fd]->func_recv = connect_client;
+ session[fd]->created = time(NULL);
+ session[fd]->connected = 1;
+ currentuse++;
return fd;
}
@@ -257,6 +279,11 @@ int make_connection(long ip,int port)
fd = socket( AF_INET, SOCK_STREAM, 0 );
if(fd_max<=fd) fd_max=fd+1;
+ else if (fd == -1) {
+ perror("socket");
+ return -1;
+ }
+
// setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,NULL,0);
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); // reuse fix
#ifdef SO_REUSEPORT
@@ -292,7 +319,10 @@ int make_connection(long ip,int port)
session[fd]->func_recv = recv_to_fifo;
session[fd]->func_send = send_from_fifo;
session[fd]->func_parse = default_func_parse;
+ session[fd]->created = time(NULL);
+ session[fd]->connected = 1;
+ currentuse++;
return fd;
}
@@ -311,6 +341,13 @@ int delete_session(int fd)
free(session[fd]);
}
session[fd]=NULL;
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+ currentuse--;
+ if (currentuse<0) {
+ printf("delete_session: current sessions negative!\n");
+ currentuse=0;
+ }
//printf("delete_session:%d\n",fd);
return 0;
}
@@ -390,6 +427,10 @@ int do_parsepacket(void)
for(i=0;i<fd_max;i++){
if(!session[i])
continue;
+ if(!session[i]->connected && time(NULL)-session[i]->created > CONNECT_TIMEOUT) {
+ printf("Session #%d timed out\n", i);
+ session[i]->eof = 1;
+ }
if(session[i]->rdata_size==0 && session[i]->eof==0)
continue;
if(session[i]->func_parse){
@@ -405,6 +446,7 @@ int do_parsepacket(void)
void do_socket(void)
{
FD_ZERO(&readfds);
+ currentuse = 2;
}
int RFIFOSKIP(int fd,int len)
@@ -438,3 +480,26 @@ int Net_Init(void)
return(0);
}
+int fclose_(FILE *fp)
+{
+ int res = fclose(fp);
+ if (res == 0)
+ currentuse--;
+// printf("file closed: used: %d\n",currentuse);
+ return res;
+}
+
+FILE *fopen_(const char *path, const char *mode)
+{
+ FILE *f = fopen(path, mode);
+ if (f != NULL)
+ currentuse++;
+// printf("file opened: used: %d\n",currentuse);
+ return f;
+}
+
+int free_fds()
+{
+ return (currentuse+1 < SOFT_LIMIT) ? 1 : 0;
+}
+
diff --git a/src/common/socket.h b/src/common/socket.h
index fe06e40..b67e660 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -12,6 +12,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#endif
+#include <time.h>
// define declaration
@@ -44,13 +45,14 @@
#define FD_SETSIZE 4096
#endif // __INTERIX
-
/* Removed Cygwin FD_SETSIZE declarations, now are directly passed on to the compiler through Makefile [Valaris] */
// Struct declaration
struct socket_data{
int eof;
+ time_t created;
+ int connected;
unsigned char *rdata,*wdata;
int max_rdata,max_wdata;
int rdata_size,wdata_size;
@@ -71,6 +73,13 @@ struct socket_data{
#endif
+// save file descriptors for important stuff
+#define SOFT_LIMIT (FD_SETSIZE - 50)
+
+// socket timeout to establish a full connection in seconds
+#define CONNECT_TIMEOUT 15
+
+
extern struct socket_data *session[FD_SETSIZE];
extern int rfifo_size,wfifo_size;
@@ -93,4 +102,9 @@ void set_defaultparse(int (*defaultparse)(int));
int Net_Init(void);
+int fclose_(FILE *fp);
+FILE *fopen_(const char *path, const char *mode);
+
+int free_fds();
+
#endif // _SOCKET_H_