diff options
author | amber <amber@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2005-04-07 18:00:13 +0000 |
---|---|---|
committer | amber <amber@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2005-04-07 18:00:13 +0000 |
commit | 1a348ede4934a1ba78f337ee1dffe11a699f4bef (patch) | |
tree | 883d4c1ae282fb67e1720f81c20f564499298ff4 /src/common | |
parent | 7cb0d361f1b4260b47ab1da99224332947320553 (diff) | |
parent | a6cd6538e4271ea08dc86803e8b7e8c8f235960b (diff) | |
download | hercules-1a348ede4934a1ba78f337ee1dffe11a699f4bef.tar.gz hercules-1a348ede4934a1ba78f337ee1dffe11a699f4bef.tar.bz2 hercules-1a348ede4934a1ba78f337ee1dffe11a699f4bef.tar.xz hercules-1a348ede4934a1ba78f337ee1dffe11a699f4bef.zip |
branch for major stability breakage
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@1440 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/GNUmakefile | 14 | ||||
-rw-r--r-- | src/common/Makefile | 33 | ||||
-rw-r--r-- | src/common/buffer.h | 18 | ||||
-rw-r--r-- | src/common/core.c | 250 | ||||
-rw-r--r-- | src/common/core.h | 11 | ||||
-rw-r--r-- | src/common/db.c | 203 | ||||
-rw-r--r-- | src/common/db.h | 25 | ||||
-rw-r--r-- | src/common/dll.h | 25 | ||||
-rw-r--r-- | src/common/grfio.c | 251 | ||||
-rw-r--r-- | src/common/grfio.h | 3 | ||||
-rw-r--r-- | src/common/lock.c | 44 | ||||
-rw-r--r-- | src/common/malloc.c | 510 | ||||
-rw-r--r-- | src/common/malloc.h | 66 | ||||
-rw-r--r-- | src/common/mmo.h | 78 | ||||
-rw-r--r-- | src/common/nullpo.h | 11 | ||||
-rw-r--r-- | src/common/showmsg.c | 125 | ||||
-rw-r--r-- | src/common/showmsg.h | 93 | ||||
-rw-r--r-- | src/common/socket.c | 672 | ||||
-rw-r--r-- | src/common/socket.h | 32 | ||||
-rw-r--r-- | src/common/strlib.c | 98 | ||||
-rw-r--r-- | src/common/strlib.h | 13 | ||||
-rw-r--r-- | src/common/timer.c | 290 | ||||
-rw-r--r-- | src/common/timer.h | 12 | ||||
-rw-r--r-- | src/common/utils.c | 16 | ||||
-rw-r--r-- | src/common/utils.h | 18 |
25 files changed, 2349 insertions, 562 deletions
diff --git a/src/common/GNUmakefile b/src/common/GNUmakefile deleted file mode 100644 index b15d4d481..000000000 --- a/src/common/GNUmakefile +++ /dev/null @@ -1,14 +0,0 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h - -clean: - rm -f *.o diff --git a/src/common/Makefile b/src/common/Makefile index b15d4d481..7a00c5a3c 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,14 +1,23 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h +txt sql all: obj common + +obj: + mkdir obj + +common: obj/core.o obj/socket.o obj/timer.o obj/grfio.o obj/db.o obj/lock.o obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o + +obj/%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +obj/core.o: core.c core.h showmsg.h +obj/socket.o: socket.c socket.h mmo.h showmsg.h dll.h +obj/timer.o: timer.c timer.h showmsg.h +obj/grfio.o: grfio.c grfio.h showmsg.h +obj/db.o: db.c db.h showmsg.h +obj/lock.o: lock.h showmsg.h +obj/nullpo.o: nullpo.c nullpo.h showmsg.h +obj/malloc.o: malloc.c malloc.h showmsg.h +obj/showmsg.o: showmsg.c showmsg.h +obj/strlib.o: strlib.c strlib.h utils.h clean: - rm -f *.o + rm -rf *.o obj diff --git a/src/common/buffer.h b/src/common/buffer.h new file mode 100644 index 000000000..ea94380ce --- /dev/null +++ b/src/common/buffer.h @@ -0,0 +1,18 @@ +#ifndef _BUFFER_H_ +#define _BUFFER_H_ + +// Full credit for this goes to Shinomori [Ajarn] + +#ifdef __GNUC__ // GCC has variable length arrays + +#define CREATE_BUFFER(name, type, size) type name[size] +#define DELETE_BUFFER(name) + +#else // others don't, so we emulate them + +#define CREATE_BUFFER(name, type, size) type *name=(type*)aCalloc(size,sizeof(type)) +#define DELETE_BUFFER(name) aFree(name);name=NULL + +#endif + +#endif diff --git a/src/common/core.c b/src/common/core.c index 167b38efb..0a9e76120 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -8,17 +8,29 @@ #endif #include <signal.h> #include <string.h> +#ifdef DUMPSTACK + #ifndef CYGWIN // HAVE_EXECINFO_H + #include <execinfo.h> + #endif +#endif #include "core.h" -#include "socket.h" -#include "timer.h" -#include "version.h" -#include "showmsg.h" +#include "../common/mmo.h" +#include "../common/malloc.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/version.h" +#include "../common/showmsg.h" #ifdef MEMWATCH #include "memwatch.h" #endif +char *argp; +int runflag = 1; +char SERVER_TYPE = SERVER_NONE; +unsigned long ticks = 0; // by MC Cameri +char pid_file[256]; static void (*term_func)(void)=NULL; /*====================================== @@ -30,14 +42,54 @@ void set_termfunc(void (*termfunc)(void)) term_func = termfunc; } +// Added by Gabuzomeu +// +// This is an implementation of signal() using sigaction() for portability. +// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced +// Programming in the UNIX Environment_. +// +#ifndef SIGPIPE +#define SIGPIPE SIGINT +#endif + +#ifndef POSIX +#define compat_signal(signo, func) signal(signo, func) +#else +sigfunc *compat_signal(int signo, sigfunc *func) +{ + struct sigaction sact, oact; + + sact.sa_handler = func; + sigemptyset(&sact.sa_mask); + sact.sa_flags = 0; +#ifdef SA_INTERRUPT + sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +#endif + + if (sigaction(signo, &sact, &oact) < 0) + return (SIG_ERR); + + return (oact.sa_handler); +} +#endif + /*====================================== * CORE : Signal Sub Function *-------------------------------------- */ - +// for handling certain signals ourselves, like SIGPIPE +static void sig_ignore(int sn) { + printf ("Broken pipe found... closing socket\n"); // set to eof in socket.c + return; // does nothing here +} static void sig_proc(int sn) { int i; + static int is_called = 0; + + if(is_called++) + return; + switch(sn){ case SIGINT: case SIGTERM: @@ -53,6 +105,66 @@ static void sig_proc(int sn) } } +/*========================================= + * Dumps the stack using glibc's backtrace + *----------------------------------------- + */ +#ifndef DUMPSTACK + #define sig_dump SIG_DFL +#else + #ifdef CYGWIN + #define FOPEN_ freopen + extern void cygwin_stackdump(); + #else + #define FOPEN_(fn,m,s) fopen(fn,m) + #endif +extern const char *strsignal(int); +void sig_dump(int sn) +{ + FILE *fp; + char file[256]; + int no = 0; + + #ifndef CYGWIN + void* array[20]; + char **stack; + size_t size; + #endif + + // search for a usable filename + do { + sprintf (file, "log/%s%04d.stackdump", argp, ++no); + } while((fp = fopen(file,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + + if ((fp = FOPEN_(file, "w", stderr)) != NULL) { + printf ("Dumping stack... "); + fprintf(fp, "Exception: %s \n", strsignal(sn)); + fflush (fp); + + #ifdef CYGWIN + cygwin_stackdump (); + #else + fprintf(fp, "Stack trace:\n"); + size = backtrace (array, 20); + stack = backtrace_symbols (array, size); + for (no = 0; no < size; no++) { + fprintf(fp, "%s\n", stack[no]); + } + fprintf(fp,"End of stack trace\n"); + aFree(stack); + #endif + + printf ("Done.\n"); + fflush(stdout); + fclose(fp); + } + // Pass the signal to the system's default handler + compat_signal(sn, SIG_DFL); + raise(sn); +} +#endif + int get_svn_revision(char *svnentry) { // Warning: minor syntax checking char line[1024]; int rev = 0; @@ -60,12 +172,13 @@ int get_svn_revision(char *svnentry) { // Warning: minor syntax checking if ((fp = fopen(svnentry, "r")) == NULL) { return 0; } else { - while (fgets(line,1023,fp)) if (strstr(line,"revision=")) break; + while (fgets(line,1023,fp)) + if (strstr(line,"revision=")) break; fclose(fp); - if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev)==1) - return rev; + if (sscanf(line," %*[^\"]\"%d%*[^\n]",&rev) == 1) + return rev; else - return 0; + return 0; } // return 0; } @@ -87,7 +200,7 @@ static void display_title(void) // \033[1m : use bold for font printf("\033[2J"); // clear screen and go up/left (0, 0 position in text) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n"); // white writing (37) on blue background (44), \033[K clean until end of file - printf("\033[0;44m (\033[1;33m (c)2004 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m (c)2005 eAthena Development Team presents \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[0;44m (\033[1m ______ __ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m /\\ _ \\/\\ \\__/\\ \\ v%2d.%02d.%02d \033[0;44m)\033[K\033[0m\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m __\\ \\ \\_\\ \\ \\ ,_\\ \\ \\___ __ ___ __ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char @@ -100,80 +213,115 @@ static void display_title(void) printf("\033[0;44m (\033[1m ( e | n | g | l | i | s | h ) ( A | t | h | e | n | a ) \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \\_/ \033[0;44m)\033[K\033[0m\n"); // 1: bold char, 0: normal char printf("\033[0;44m (\033[1m \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) - printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2004 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) + printf("\033[0;44m (\033[1;33m Advanced Fusion Maps (c) 2003-2005 The Fusion Project \033[0;44m)\033[K\033[0m\n"); // yellow writing (33) printf("\033[37;44m (=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=)\033[K\033[0m\n\n"); // reset color if ((revision = get_svn_revision(".svn\\entries"))>0) { - snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: %d.\n",revision); + snprintf(tmp_output,sizeof(tmp_output),"SVN Revision: '"CL_WHITE"%d"CL_RESET"'.\n",revision); ShowInfo(tmp_output); } } -// Added by Gabuzomeu -// -// This is an implementation of signal() using sigaction() for portability. -// (sigaction() is POSIX; signal() is not.) Taken from Stevens' _Advanced -// Programming in the UNIX Environment_. -// -#ifndef SIGPIPE -#define SIGPIPE SIGINT -#endif +/*====================================== + * CORE : MAINROUTINE + *-------------------------------------- + */ -#ifndef POSIX -#define compat_signal(signo, func) signal(signo, func) -#else -sigfunc *compat_signal(int signo, sigfunc *func) -{ - struct sigaction sact, oact; +void pid_delete(void) { + unlink(pid_file); +} - sact.sa_handler = func; - sigemptyset(&sact.sa_mask); - sact.sa_flags = 0; -#ifdef SA_INTERRUPT - sact.sa_flags |= SA_INTERRUPT; /* SunOS */ +void pid_create(const char* file) { + FILE *fp; + int len = strlen(file); + strcpy(pid_file,file); + if(len > 4 && pid_file[len - 4] == '.') { + pid_file[len - 4] = 0; + } + strcat(pid_file,".pid"); + fp = fopen(pid_file,"w"); + if(fp) { +#ifdef _WIN32 + fprintf(fp,"%d",GetCurrentProcessId()); +#else + fprintf(fp,"%d",getpid()); #endif + fclose(fp); + atexit(pid_delete); + } +} - if (sigaction(signo, &sact, &oact) < 0) - return (SIG_ERR); +#define LOG_UPTIME 0 +void log_uptime(void) +{ +#if LOG_UPTIME + time_t curtime; + char curtime2[24]; + FILE *fp; + long seconds = 0, day = 24*60*60, hour = 60*60, + minute = 60, days = 0, hours = 0, minutes = 0; - return (oact.sa_handler); -} -#endif + fp = fopen("log/uptime.log","a"); + if (fp) { + time(&curtime); + strftime(curtime2, 24, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + seconds = (gettick()-ticks)/CLOCKS_PER_SEC; + days = seconds/day; + seconds -= (seconds/day>0)?(seconds/day)*day:0; + hours = seconds/hour; + seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; + minutes = seconds/minute; + seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; -/*====================================== - * CORE : MAINROUTINE - *-------------------------------------- - */ + fprintf(fp, "%s: %s uptime - %ld days, %ld hours, %ld minutes, %ld seconds.\n", + curtime2, argp, days, hours, minutes, seconds); + fclose(fp); + } -int runflag = 1; + return; +#endif +} int main(int argc,char **argv) { int next; + if ((argp = strstr(argv[0], "./")) != NULL) + argp+=2; + else argp = argv[0]; + + display_title(); + + do_init_memmgr(argp); // 一番最初に実行する必要がある + atexit(log_uptime); + pid_create(argp); Net_Init(); do_socket(); - compat_signal(SIGPIPE,SIG_IGN); + compat_signal(SIGPIPE, sig_ignore); compat_signal(SIGTERM,sig_proc); compat_signal(SIGINT,sig_proc); - + // Signal to create coredumps by system when necessary (crash) - compat_signal(SIGSEGV, SIG_DFL); -#ifndef _WIN32 - compat_signal(SIGBUS, SIG_DFL); - compat_signal(SIGTRAP, SIG_DFL); -#endif - compat_signal(SIGILL, SIG_DFL); + compat_signal(SIGSEGV, sig_dump); + compat_signal(SIGFPE, sig_dump); + compat_signal(SIGILL, sig_dump); + #ifndef _WIN32 + compat_signal(SIGBUS, sig_dump); + compat_signal(SIGTRAP, SIG_DFL); + #endif - display_title(); + tick_ = time(0); + ticks = gettick(); do_init(argc,argv); + while(runflag){ next=do_timer(gettick_nocache()); do_sendrecv(next); do_parsepacket(); } + return 0; } diff --git a/src/common/core.h b/src/common/core.h index bc2be02c2..e9b5c8227 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -3,10 +3,19 @@ #ifndef _CORE_H_ #define _CORE_H_ +extern char *argp; extern int runflag; +extern unsigned long ticks; +extern char SERVER_TYPE; -int do_init(int,char**); +enum { + SERVER_NONE, + SERVER_LOGIN, + SERVER_CHAR, + SERVER_MAP, +}; +int do_init(int,char**); void set_termfunc(void (*termfunc)(void)); #endif // _CORE_H_ diff --git a/src/common/db.c b/src/common/db.c index 58f0ea4f7..377128e8f 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -1,18 +1,26 @@ // $Id: db.c,v 1.2 2004/09/23 14:43:06 MouseJstr Exp $ -// #define MALLOC_DBN #include <stdio.h> #include <stdlib.h> #include <string.h> #include "db.h" #include "mmo.h" #include "utils.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" #endif -#define ROOT_SIZE 4096 +//#define MALLOC_DBN + +// Backup cleaning routine in case the core doesn't do so properly, +// only enabled if malloc_dbn is not defined. +// As a temporary solution the root of the problem should still be found and fixed +struct dbn *head; +struct dbn *tail; + #ifdef MALLOC_DBN +#define ROOT_SIZE 4096 static struct dbn *dbn_root[512], *dbn_free; static int dbn_root_rest=0,dbn_root_num=0; @@ -39,20 +47,50 @@ static void free_dbn(struct dbn* add_dbn) add_dbn->parent = dbn_free; dbn_free = add_dbn; } + +void exit_dbn(void) +{ + int i; + + for (i=0;i<dbn_root_num;i++) + if (dbn_root[i]) + aFree(dbn_root[i]); + + dbn_root_rest=0; + dbn_root_num=0; + + return; +} +#else +void exit_dbn(void) +{ + int i = 0; + struct dbn *p = head, *p2; + while (p) { + p2 = p->next; + aFree(p); + p = p2; + i++; + } + //printf ("freed %d stray dbn\n", i); + return; +} #endif +// maybe change the void* to const char* ??? static int strdb_cmp(struct dbt* table,void* a,void* b) { if(table->maxlen) - return strncmp(a,b,table->maxlen); - return strcmp(a,b); + return strncmp((const char*)a,(const char*)b,table->maxlen); + return strcmp((const char*)a,(const char*)b); } +// maybe change the void* to unsigned char* ??? static unsigned int strdb_hash(struct dbt* table,void* a) { int i; unsigned int h; - unsigned char *p=a; + unsigned char *p = (unsigned char*)a; i=table->maxlen; if(i==0) i=0x7fffffff; @@ -62,7 +100,7 @@ static unsigned int strdb_hash(struct dbt* table,void* a) return h; } -struct dbt* strdb_init(int maxlen) +struct dbt* strdb_init_(int maxlen,const char *file,int line) { int i; struct dbt* table; @@ -74,6 +112,9 @@ struct dbt* strdb_init(int maxlen) table->maxlen=maxlen; for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -95,7 +136,7 @@ static unsigned int numdb_hash(struct dbt* table,void* a) return (unsigned int)a; } -struct dbt* numdb_init(void) +struct dbt* numdb_init_(const char *file,int line) { int i; struct dbt* table; @@ -107,6 +148,9 @@ struct dbt* numdb_init(void) table->maxlen=sizeof(int); for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -130,14 +174,14 @@ void * db_search2(struct dbt *table, const char *key) { int i,sp; struct dbn *p,*pn,*stack[64]; - int slen = strlen(key); + int slen = strlen(key); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - if (strnicmp(key, p->key, slen) == 0) + if (strnicmp(key, (const char*)p->key, slen) == 0) return p->data; if((pn=p->left)!=NULL){ if(p->right){ @@ -345,6 +389,29 @@ static void db_rebalance_erase(struct dbn *z,struct dbn **root) } } +void db_free_lock(struct dbt *table) { + table->free_lock++; +} + +void db_free_unlock(struct dbt *table) { + if(--table->free_lock == 0) { + int i; + for(i = 0; i < table->free_count ; i++) { + db_rebalance_erase(table->free_list[i].z,table->free_list[i].root); + if(table->cmp == strdb_cmp) { + aFree(table->free_list[i].z->key); + } +#ifdef MALLOC_DBN + free_dbn(table->free_list[i].z); +#else + aFree(table->free_list[i].z); +#endif + table->item_count--; + } + table->free_count = 0; + } +} + struct dbn* db_insert(struct dbt *table,void* key,void* data) { struct dbn *p,*priv; @@ -354,10 +421,33 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) for(c=0,priv=NULL ,p = table->ht[hash];p;){ c=table->cmp(table,key,p->key); if(c==0){ // replace - if (table->release) - table->release(p, 3); + if (table->release) + table->release(p, 3); + if(p->deleted) { + // 削除されたデータなので、free_list 上の削除予定を消す + int i; + for(i = 0; i < table->free_count ; i++) { + if(table->free_list[i].z == p) { + memmove( + &table->free_list[i], + &table->free_list[i+1], + sizeof(struct db_free)*(table->free_count - i - 1) + ); + break; + } + } + if(i == table->free_count || table->free_count <= 0) { + printf("db_insert: cannnot find deleted db node.\n"); + } else { + table->free_count--; + if(table->cmp == strdb_cmp) { + aFree(p->key); + } + } + } p->data=data; p->key=key; + p->deleted = 0; return p; } priv=p; @@ -382,6 +472,17 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) p->key = key; p->data = data; p->color = RED; + p->deleted = 0; + p->prev = NULL; + p->next = NULL; + if (head == NULL) + head = tail = p; + else { + p->prev = tail; + tail->next = p; + tail = p; + } + if(c==0){ // hash entry is empty table->ht[hash] = p; p->color = BLACK; @@ -397,6 +498,8 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) db_rebalance(p,&table->ht[hash]); } } + table->item_count++; + return p; } @@ -419,29 +522,69 @@ void* db_erase(struct dbt *table,void* key) if(!p) return NULL; data=p->data; - db_rebalance_erase(p,&table->ht[hash]); -#ifdef MALLOC_DBN - free_dbn(p); -#else - free(p); -#endif + if(table->free_lock) { + if(table->free_count == table->free_max) { + table->free_max += 32; + table->free_list = (struct db_free*)realloc(table->free_list,sizeof(struct db_free) * table->free_max); + } + table->free_list[table->free_count].z = p; + table->free_list[table->free_count].root = &table->ht[hash]; + table->free_count++; + p->deleted = 1; + p->data = NULL; + if(table->cmp == strdb_cmp) { + if(table->maxlen) { + char *key = (char*)malloc(table->maxlen); + memcpy(key,p->key,table->maxlen); + p->key = key; + } else { + p->key = strdup((const char*)p->key); + } + } + } else { + db_rebalance_erase(p,&table->ht[hash]); + if (p->prev) + p->prev->next = p->next; + else + head = p->next; + if (p->next) + p->next->prev = p->prev; + else + tail = p->prev; + + #ifdef MALLOC_DBN + free_dbn(p); + #else + aFree(p); + #endif + table->item_count--; + } return data; } void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) { int i,sp; + int count = table->item_count; // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫 struct dbn *p,*pn,*stack[64]; va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - func(p->key,p->data,ap); + //reverted it back. sorry that brought thios bug from Freya [Lupus] + //if (!p->data) { + // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key); + //} else { + if(!p->deleted) + func(p->key, p->data, ap); + count--; + //} if((pn=p->left)!=NULL){ if(p->right){ stack[sp++]=p->right; @@ -458,6 +601,13 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) } } } + db_free_unlock(table); + if(count) { + printf( + "db_foreach : data lost %d item(s) allocated from %s line %d\n", + count,table->alloc_file,table->alloc_line + ); + } va_end(ap); } @@ -468,12 +618,13 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) va_list ap; va_start(ap,func); + db_free_lock(table); for(i=0;i<HASH_SIZE;i++){ if((p=table->ht[i])==NULL) continue; sp=0; while(1){ - if(func) + if(func && !p->deleted) func(p->key,p->data,ap); if((pn=p->left)!=NULL){ if(p->right){ @@ -488,14 +639,24 @@ void db_final(struct dbt *table,int (*func)(void*,void*,va_list),...) pn=stack[--sp]; } } + if (p->prev) + p->prev->next = p->next; + else + head = p->next; + if (p->next) + p->next->prev = p->prev; + else + tail = p->prev; #ifdef MALLOC_DBN free_dbn(p); #else - free(p); + aFree(p); #endif p=pn; } } - free(table); + db_free_unlock(table); + aFree(table->free_list); + aFree(table); va_end(ap); } diff --git a/src/common/db.h b/src/common/db.h index ea9aceab0..6980099cf 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -13,6 +13,14 @@ struct dbn { int color; void *key; void *data; + int deleted; // 削除済みフラグ(db_foreach) + struct dbn *next; + struct dbn *prev; +}; + +struct db_free { + struct dbn *z; + struct dbn **root; }; struct dbt { @@ -22,6 +30,15 @@ struct dbt { void (*release)(struct dbn*,int which); int maxlen; struct dbn *ht[HASH_SIZE]; + int item_count; // vf? + const char* alloc_file; // DB?t@C + int alloc_line; // DB?s + // db_foreach 内部でdb_erase される対策として、 + // db_foreach が終わるまでロックすることにする + struct db_free *free_list; + int free_count; + int free_max; + int free_lock; }; #define strdb_search(t,k) db_search((t),(void*)(k)) @@ -34,14 +51,18 @@ struct dbt { #define numdb_erase(t,k) db_erase ((t),(void*)(k)) #define numdb_foreach db_foreach #define numdb_final db_final +#define strdb_init(a) strdb_init_(a,__FILE__,__LINE__) +#define numdb_init() numdb_init_(__FILE__,__LINE__) + +struct dbt* strdb_init_(int maxlen,const char *file,int line); +struct dbt* numdb_init_(const char *file,int line); -struct dbt* strdb_init(int maxlen); -struct dbt* numdb_init(void); void* db_search(struct dbt *table,void* key); void* db_search2(struct dbt *table, const char *key); // [MouseJstr] struct dbn* db_insert(struct dbt *table,void* key,void* data); void* db_erase(struct dbt *table,void* key); void db_foreach(struct dbt*,int(*)(void*,void*,va_list),...); void db_final(struct dbt*,int(*)(void*,void*,va_list),...); +void exit_dbn(void); #endif diff --git a/src/common/dll.h b/src/common/dll.h new file mode 100644 index 000000000..50854da4d --- /dev/null +++ b/src/common/dll.h @@ -0,0 +1,25 @@ +
+#ifndef _DLL_H_
+#define _DLL_H_
+
+#ifdef _WIN32
+
+ #include <windows.h>
+ #define DLL_OPEN(x) LoadLibrary(x)
+ #define DLL_SYM(x,y,z) (FARPROC)(x) = GetProcAddress(y,z)
+ #define DLL_CLOSE(x) FreeLibrary(x)
+ #define DLL HINSTANCE
+
+#else
+
+ #include <dlfcn.h>
+ #define DLL_OPEN(x) dlopen(x,RTLD_NOW)
+ #define DLL_SYM(x,y,z) (x) = (void *)dlsym(y,z)
+ #define DLL_CLOSE(x) dlclose(x)
+ #define DLL void *
+
+#endif
+
+#endif // _DLL_H_
+
+
diff --git a/src/common/grfio.c b/src/common/grfio.c index ff01b6e76..1a3829bf7 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -25,11 +25,50 @@ #include <ctype.h> #include <sys/stat.h> -#include <zlib.h> - -#include "utils.h" #include "grfio.h" -#include "mmo.h" +#include "../common/utils.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/malloc.h" + +#ifdef _WIN32 + #ifdef LOCALZLIB + #include "zlib.h" + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd + #else + #include "../lib/zlib_win32.h" + #include "../common/dll.h" + DLL zlib_dll; + #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) + #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) + + int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); + int (WINAPI* zlib_inflate) (z_streamp strm, int flush); + int (WINAPI* zlib_inflateEnd) (z_streamp strm); + + int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); + int (WINAPI* zlib_deflate) (z_streamp strm, int flush); + int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #endif +#else + #ifdef LOCALZLIB + #include "zlib/zlib.h" + #else + #include <zlib.h> + #endif + + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd +#endif #ifdef MEMWATCH #include "memwatch.h" @@ -72,7 +111,7 @@ typedef struct { //Since char defines *FILELIST.gentry, the maximum which can be added by grfio_add becomes by 127 pieces. #define GENTRY_LIMIT 127 -#define FILELIST_LIMIT 32768 // temporary maximum, and a theory top maximum are 2G. +#define FILELIST_LIMIT 65536 // temporary maximum, and a theory top maximum are 2G. static FILELIST *filelist; static int filelist_entrys; @@ -139,7 +178,11 @@ static unsigned char NibbleData[4][64]={ */ static unsigned int getlong(unsigned char *p) { - return *p+p[1]*256+(p[2]+p[3]*256)*65536; +// return *p+p[1]*256+(p[2]+p[3]*256)*65536; + return p[0] + | p[1] << 0x08 + | p[2] << 0x10 + | p[3] << 0x18; // Shinomori } /*========================================== @@ -157,15 +200,17 @@ static void BitConvert(BYTE *Src,char *BitSwapTable) { int lop,prm; BYTE tmp[8]; - *(DWORD*)tmp=*(DWORD*)(tmp+4)=0; +// *(DWORD*)tmp=*(DWORD*)(tmp+4)=0; + memset(tmp,0,8); for(lop=0;lop!=64;lop++) { prm = BitSwapTable[lop]-1; if (Src[(prm >> 3) & 7] & BitMaskTable[prm & 7]) { tmp[(lop >> 3) & 7] |= BitMaskTable[lop & 7]; } } - *(DWORD*)Src = *(DWORD*)tmp; - *(DWORD*)(Src+4) = *(DWORD*)(tmp+4); +// *(DWORD*)Src = *(DWORD*)tmp; +// *(DWORD*)(Src+4) = *(DWORD*)(tmp+4); + memcpy(Src,tmp,8); } static void BitConvert4(BYTE *Src) @@ -193,7 +238,11 @@ static void BitConvert4(BYTE *Src) tmp[(lop >> 3) + 4] |= BitMaskTable[lop & 7]; } } - *(DWORD*)Src ^= *(DWORD*)(tmp+4); +// *(DWORD*)Src ^= *(DWORD*)(tmp+4); + Src[0] ^= tmp[4]; + Src[1] ^= tmp[5]; + Src[2] ^= tmp[6]; + Src[3] ^= tmp[7]; } static void decode_des_etc(BYTE *buf,int len,int type,int cycle) @@ -248,7 +297,7 @@ static void decode_des_etc(BYTE *buf,int len,int type,int cycle) * Grf data decode sub : zip *------------------------------------------ */ -static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen) +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { z_stream stream; int err; @@ -258,26 +307,57 @@ static int decode_zip(Bytef* dest, uLongf* destLen, const Bytef* source, uLong s /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - stream.next_out = dest; + stream.next_out = (Bytef*) dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = zlib_inflateInit(&stream); + if (err != Z_OK) return err; + + err = zlib_inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + zlib_inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = zlib_inflateEnd(&stream); + return err; +} + +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) { + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = (Bytef*) dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; - err = inflateInit(&stream); + err = zlib_deflateInit(&stream,Z_DEFAULT_COMPRESSION); if (err != Z_OK) return err; - err = inflate(&stream, Z_FINISH); + err = zlib_deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { - inflateEnd(&stream); + zlib_inflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; - err = inflateEnd(&stream); + err = zlib_deflateEnd(&stream); return err; } + /*********************************************************** *** File List Sobroutines *** ***********************************************************/ @@ -315,7 +395,7 @@ FILELIST *filelist_find(char *fname) { int hash; - for(hash=filelist_hash[filehash(fname)];hash>=0;hash=filelist[hash].next) { + for(hash=filelist_hash[filehash((unsigned char *) fname)];hash>=0;hash=filelist[hash].next) { if(strcmpi(filelist[hash].fn,fname)==0) break; } @@ -339,7 +419,7 @@ static FILELIST* filelist_add(FILELIST *entry) } if (filelist_entrys>=filelist_maxentry) { - FILELIST *new_filelist = (FILELIST*)realloc( + FILELIST *new_filelist = (FILELIST*)aRealloc( (void*)filelist, (filelist_maxentry+FILELIST_ADDS)*sizeof(FILELIST) ); if (new_filelist != NULL) { filelist = new_filelist; @@ -354,7 +434,7 @@ static FILELIST* filelist_add(FILELIST *entry) memcpy( &filelist[filelist_entrys], entry, sizeof(FILELIST) ); - hash = filehash(entry->fn); + hash = filehash((unsigned char *) entry->fn); filelist[filelist_entrys].next = filelist_hash[hash]; filelist_hash[hash] = filelist_entrys; @@ -384,7 +464,7 @@ static void filelist_adjust(void) { if (filelist!=NULL) { if (filelist_maxentry>filelist_entrys) { - FILELIST *new_filelist = (FILELIST*)realloc( + FILELIST *new_filelist = (FILELIST*)aRealloc( (void*)filelist,filelist_entrys*sizeof(FILELIST) ); if (new_filelist != NULL) { filelist = new_filelist; @@ -443,17 +523,17 @@ int grfio_size(char *fname) entry = filelist_find(fname); if (entry==NULL || entry->gentry<0) { // LocalFileCheck - char lfname[256],rname[256],*p; + char lfname[256],*rname,*p; FILELIST lentry; struct stat st; - - if(strcmp(data_dir, "") != 0) { + + if(strcmp(data_dir, "") != 0 && (rname=grfio_resnametable(fname,lfname))!=NULL) { //printf("%s\t",fname); - sprintf(rname,"%s",grfio_resnametable(fname,lfname)); + //sprintf(rname,"%s",grfio_resnametable(fname,lfname)); //printf("%s\n",rname); sprintf(lfname,"%s%s",data_dir,rname); //printf("%s\n",lfname); - } + } for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix @@ -485,13 +565,18 @@ void* grfio_reads(char *fname, int *size) entry = filelist_find(fname); if (entry==NULL || entry->gentry<=0) { // LocalFileCheck - char lfname[256],rname[256],*p; + char lfname[256],*rname,*p; FILELIST lentry; strncpy(lfname,fname,255); - sprintf(rname,"%s",grfio_resnametable(fname,lfname)); - sprintf(lfname,"%s%s",data_dir,rname); - //printf("%s\n",lfname); + // i hope this is the correct way =p [celest] + if ((rname=grfio_resnametable(fname,lfname))!=NULL) { + char tbuf[255]; + //sprintf(rname,"%s",grfio_resnametable(fname,lfname)); + sprintf(tbuf,"%s%s",data_dir,rname); + strcpy(lfname, tbuf); + //printf("%s\n",lfname); + } for(p=&lfname[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix @@ -504,7 +589,7 @@ void* grfio_reads(char *fname, int *size) lentry.declen = ftell(in); } fseek(in,0,0); // SEEK_SET - buf2 = calloc(lentry.declen+1024, 1); + buf2 = (unsigned char *)aCallocA(lentry.declen+1024, 1); if (buf2==NULL) { printf("file read memory allocate error : declen\n"); goto errret; @@ -520,13 +605,13 @@ void* grfio_reads(char *fname, int *size) } else { printf("%s not found (grfio_reads)\n", fname); //goto errret; - free(buf2); + aFree(buf2); return NULL; } } } if (entry!=NULL && entry->gentry>0) { // Archive[GRF] File Read - buf = calloc(entry->srclen_aligned+1024, 1); + buf = (unsigned char *) aCallocA(entry->srclen_aligned+1024, 1); if (buf==NULL) { printf("file read memory allocate error : srclen_aligned\n"); goto errret; @@ -536,13 +621,13 @@ void* grfio_reads(char *fname, int *size) if(in==NULL) { printf("%s not found (grfio_reads)\n",gfname); //goto errret; - free(buf); + aFree(buf); return NULL; } fseek(in,entry->srcpos,0); fread(buf,1,entry->srclen_aligned,in); fclose(in); - buf2=calloc(entry->declen+1024, 1); + buf2 = (unsigned char *)aCallocA(entry->declen+1024, 1); if (buf2==NULL) { printf("file decode memory allocate error\n"); goto errret; @@ -561,16 +646,16 @@ void* grfio_reads(char *fname, int *size) } else { memcpy(buf2,buf,entry->declen); } - free(buf); + aFree(buf); } if (size!=NULL && entry!=NULL) *size = entry->declen; return buf2; errret: - if (buf!=NULL) free(buf); - if (buf2!=NULL) free(buf2); + if (buf!=NULL) aFree(buf); + if (buf2!=NULL) aFree(buf2); if (in!=NULL) fclose(in); - exit(1); //return NULL; + return NULL; } /*========================================== @@ -586,7 +671,7 @@ void* grfio_read(char *fname) * Resource filename decode *------------------------------------------ */ -static unsigned char * decode_filename(unsigned char *buf,int len) +static char * decode_filename(unsigned char *buf,int len) { int lop; for(lop=0;lop<len;lop+=8) { @@ -595,7 +680,7 @@ static unsigned char * decode_filename(unsigned char *buf,int len) BitConvert4(&buf[lop]); BitConvert(&buf[lop],BitSwapTable2); } - return buf; + return (char*)buf; } /*========================================== @@ -608,12 +693,13 @@ static int grfio_entryread(char *gfname,int gentry) int grf_size,list_size; unsigned char grf_header[0x2e]; int lop,entry,entrys,ofs,grf_version; - unsigned char *fname; + char *fname; unsigned char *grf_filelist; fp = fopen(gfname,"rb"); if(fp==NULL) { - printf("%s not found (grfio_entryread)\n",gfname); + sprintf(tmp_output,"GRF Data File not found: '"CL_WHITE"%s"CL_RESET"'.\n",gfname); + ShowWarning(tmp_output); return 1; // 1:not found error } @@ -621,7 +707,7 @@ static int grfio_entryread(char *gfname,int gentry) grf_size = ftell(fp); 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 + if(strcmp((const char *) grf_header,"Master of Magic") || fseek(fp,getlong(grf_header+0x1e),1)){ // SEEK_CUR fclose(fp); printf("%s read error\n",gfname); return 2; // 2:file format error @@ -631,7 +717,7 @@ static int grfio_entryread(char *gfname,int gentry) if (grf_version==0x01) { //****** Grf version 01xx ****** list_size = grf_size-ftell(fp); - grf_filelist = calloc(list_size, 1); + grf_filelist = (unsigned char *) aCallocA(list_size, 1); if(grf_filelist==NULL){ fclose(fp); printf("out of memory : grf_filelist\n"); @@ -654,7 +740,7 @@ static int grfio_entryread(char *gfname,int gentry) fname = decode_filename(grf_filelist+ofs+6,grf_filelist[ofs]-6); if(strlen(fname)>sizeof(aentry.fn)-1){ printf("file name too long : %s\n",fname); - free(grf_filelist); + aFree(grf_filelist); exit(1); } srclen=0; @@ -679,7 +765,7 @@ static int grfio_entryread(char *gfname,int gentry) aentry.srcpos = getlong(grf_filelist+ofs2+13)+0x2e; aentry.cycle = srccount; aentry.type = type; - strncpy(aentry.fn,fname,sizeof(aentry.fn)-1); + strncpy(aentry.fn, fname,sizeof(aentry.fn)-1); #ifdef GRFIO_LOCAL aentry.gentry = -(gentry+1); // As Flag for making it a negative number carrying out the first time LocalFileCheck #else @@ -689,7 +775,7 @@ static int grfio_entryread(char *gfname,int gentry) } ofs = ofs2 + 17; } - free(grf_filelist); + aFree(grf_filelist); } else if (grf_version==0x02) { //****** Grf version 02xx ****** unsigned char eheader[8]; @@ -706,15 +792,15 @@ static int grfio_entryread(char *gfname,int gentry) return 4; } - rBuf = calloc( rSize , 1); // Get a Read Size + rBuf = (unsigned char *)aCallocA( rSize , 1); // Get a Read Size if (rBuf==NULL) { fclose(fp); printf("out of memory : grf compress entry table buffer\n"); return 3; } - grf_filelist = calloc( eSize , 1); // Get a Extend Size + grf_filelist = (unsigned char *)aCallocA( eSize , 1); // Get a Extend Size if (grf_filelist==NULL) { - free(rBuf); + aFree(rBuf); fclose(fp); printf("out of memory : grf extract entry table buffer\n"); return 3; @@ -723,7 +809,7 @@ static int grfio_entryread(char *gfname,int gentry) fclose(fp); decode_zip(grf_filelist,&eSize,rBuf,rSize); // Decode function list_size = eSize; - free(rBuf); + aFree(rBuf); entrys = getlong(grf_header+0x26) - 7; @@ -732,13 +818,14 @@ static int grfio_entryread(char *gfname,int gentry) int ofs2,srclen,srccount,type; FILELIST aentry; - fname = grf_filelist+ofs; + fname = (char*)(grf_filelist+ofs); if (strlen(fname)>sizeof(aentry.fn)-1) { printf("grf : file name too long : %s\n",fname); - free(grf_filelist); + aFree(grf_filelist); exit(1); } - ofs2 = ofs+strlen(grf_filelist+ofs)+1; + //ofs2 = ofs+strlen((char*)(grf_filelist+ofs))+1; + ofs2 = ofs+strlen(fname)+1; type = grf_filelist[ofs2+12]; if(type==1 || type==3 || type==5) { srclen=getlong(grf_filelist+ofs2); @@ -766,7 +853,7 @@ static int grfio_entryread(char *gfname,int gentry) } ofs = ofs2 + 17; } - free(grf_filelist); + aFree(grf_filelist); } else { //****** Grf Other version ****** fclose(fp); @@ -786,11 +873,11 @@ static int grfio_entryread(char *gfname,int gentry) static void grfio_resourcecheck() { int size; - unsigned char *buf,*ptr; + char *buf,*ptr; char w1[256],w2[256],src[256],dst[256]; FILELIST *entry; - buf=grfio_reads("data\\resnametable.txt",&size); + buf = (char*)grfio_reads("data\\resnametable.txt",&size); buf[size] = 0; for(ptr=buf;ptr-buf<size;) { @@ -816,7 +903,7 @@ static void grfio_resourcecheck() if (!ptr) break; ptr++; } - free(buf); + aFree(buf); filelist_adjust(); // Unnecessary area release of filelist } @@ -836,10 +923,11 @@ int grfio_add(char *fname) exit(1); } - printf("%s file reading...\n",fname); +// sprintf(tmp_output,"Reading GRF File: '%s'.\n",fname); +// ShowStatus(tmp_output); if (gentry_entrys>=gentry_maxentry) { - char **new_gentry = (char**)realloc( + char **new_gentry = (char**)aRealloc( (void*)gentry_table,(gentry_maxentry+GENTRY_ADDS)*sizeof(char*) ); if (new_gentry!=NULL) { int lop; @@ -853,7 +941,7 @@ int grfio_add(char *fname) } } len = strlen( fname ); - buf = calloc(len+1, 1); + buf = (char*)aCallocA(len+1, 1); if (buf==NULL) { printf("out of memory : gentry\n"); exit(1); @@ -879,20 +967,30 @@ void grfio_final(void) { int lop; - if (filelist!=NULL) free(filelist); + if (filelist!=NULL) aFree(filelist); filelist = NULL; filelist_entrys = filelist_maxentry = 0; if (gentry_table!=NULL) { for(lop=0;lop<gentry_entrys;lop++) { if (gentry_table[lop]!=NULL) { - free(gentry_table[lop]); + aFree(gentry_table[lop]); } } - free(gentry_table); + aFree(gentry_table); } gentry_table = NULL; gentry_entrys = gentry_maxentry = 0; + +#ifdef _WIN32 + #ifndef LOCALZLIB + DLL_CLOSE(zlib_dll); + zlib_inflateInit_ = NULL; + zlib_inflate = NULL; + zlib_inflateEnd = NULL; + #endif +#endif + } /*========================================== @@ -905,6 +1003,24 @@ void grfio_init(char *fname) char line[1024], w1[1024], w2[1024]; int result = 0, result2 = 0, result3 = 0, result4 = 0; +#ifdef _WIN32 + #ifndef LOCALZLIB + if(!zlib_dll) { + zlib_dll = DLL_OPEN ("zlib.dll"); + DLL_SYM (zlib_inflateInit_, zlib_dll, "inflateInit_"); + DLL_SYM (zlib_inflate, zlib_dll, "inflate"); + DLL_SYM (zlib_inflateEnd, zlib_dll, "inflateEnd"); + DLL_SYM (zlib_deflateInit_, zlib_dll, "deflateInit_"); + DLL_SYM (zlib_deflate, zlib_dll, "deflate"); + DLL_SYM (zlib_deflateEnd, zlib_dll, "deflateEnd"); + if(zlib_dll == NULL) { + MessageBox(NULL,"Can't load zlib.dll","grfio.c",MB_OK); + exit(1); + } + } + #endif +#endif + data_conf = fopen(fname, "r"); // It will read, if there is grf-files.txt. @@ -923,7 +1039,8 @@ void grfio_init(char *fname) } fclose(data_conf); - printf("read %s done\n",fname); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",fname); + ShowStatus(tmp_output); } // end of reading grf-files.txt hashinit(); // hash table initialization @@ -945,9 +1062,9 @@ void grfio_init(char *fname) if (strcmp(data_dir, "") == 0) // Id data_dir doesn't exist result4 = 1; // Data directory - +/* if (result != 0 && result2 != 0 && result3 != 0 && result4 != 0) { printf("not grf file readed exit!!\n"); exit(1); // It ends, if a resource cannot read one. - } + }*/ } diff --git a/src/common/grfio.h b/src/common/grfio.h index 53b9da8d4..3fa257e2f 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -8,6 +8,9 @@ void* grfio_read(char*); // GRFIO data file read void* grfio_reads(char*,int*); // GRFIO data file read & size get int grfio_size(char*); // GRFIO data file size get +int decode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char *dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); + // Accessor to GRF filenames char *grfio_setdatafile(const char *str); char *grfio_setadatafile(const char *str); diff --git a/src/common/lock.c b/src/common/lock.c index 9a2205bf4..0258cbd2c 100644 --- a/src/common/lock.c +++ b/src/common/lock.c @@ -1,37 +1,55 @@ #include <stdio.h> +#include <errno.h> +#include <string.h> +#ifndef WIN32 +#include <unistd.h> +#else +#include <windows.h> +#define F_OK 0x0 +#define R_OK 0x4 +#endif #include "lock.h" +#include "showmsg.h" +#define exists(filename) (!access(filename, F_OK)) // 書き込みファイルの保護処理 // (書き込みが終わるまで、旧ファイルを保管しておく) // 新しいファイルの書き込み開始 -FILE* lock_fopen(const char* filename,int *info) { +FILE* lock_fopen (const char* filename, int *info) { char newfile[512]; FILE *fp; - int no = 0; + int no = 0; // 安全なファイル名を得る(手抜き) do { - sprintf(newfile,"%s_%04d.tmp",filename,++no); - } while((fp = fopen(newfile,"r")) && (fclose(fp), no<9999) ); + sprintf(newfile, "%s_%04d.tmp", filename, ++no); + } while((fp = fopen(newfile,"r")) && (fclose(fp), no < 9999)); *info = no; return fopen(newfile,"w"); } // 旧ファイルを削除&新ファイルをリネーム -int lock_fclose(FILE *fp,const char* filename,int *info) { - int ret = 0; +int lock_fclose (FILE *fp, const char* filename, int *info) { + int ret = 1; char newfile[512]; - if(fp != NULL) { + char oldfile[512]; + if (fp != NULL) { ret = fclose(fp); - sprintf(newfile,"%s_%04d.tmp",filename,*info); - remove(filename); + sprintf(newfile, "%s_%04d.tmp", filename, *info); + sprintf(oldfile, "%s.bak", filename); // old backup file + + if (exists(oldfile)) remove(oldfile); // remove backup file if it already exists + rename (filename, oldfile); // backup our older data instead of deleting it + // このタイミングで落ちると最悪。 - rename(newfile,filename); - return ret; - } else { - return 1; + if ((ret = rename(newfile,filename)) != 0) { // rename our temporary file to its correct name + sprintf(tmp_output,"%s - '"CL_WHITE"%s"CL_RESET"'\n", strerror(errno), newfile); + ShowError(tmp_output); + } } + + return ret; } diff --git a/src/common/malloc.c b/src/common/malloc.c index eda9bc218..b81c25ed5 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -1,13 +1,27 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "malloc.h" +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +// 独自メモリマネージャを使用する場合、次のコメントを外してください。 +//#define USE_MEMMGR + +#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR) + void* aMalloc_( size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: malloc %d\n",file,line,func,size); +#ifdef MEMWATCH + ret=mwMalloc(size,file,line); +#else ret=malloc(size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func); exit(1); @@ -18,9 +32,13 @@ void* aMalloc_( size_t size, const char *file, int line, const char *func ) void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size); +#ifdef MEMWATCH + ret=mwCalloc(num,size,file,line); +#else ret=calloc(num,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func); exit(1); @@ -32,9 +50,13 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size); +#ifdef MEMWATCH + ret=mwRealloc(p,size,file,line); +#else ret=realloc(p,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func); exit(1); @@ -42,3 +64,485 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f } return ret; } + +char* aStrdup_( const void *p, const char *file, int line, const char *func ) +{ + char *ret; + + // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p); +#ifdef MEMWATCH + ret=mwStrdup(p,file,line); +#else + ret= strdup((char *) p); +#endif + if(ret==NULL){ + printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func); + exit(1); + + } + return ret; +} + +void aFree_( void *p, const char *file, int line, const char *func ) +{ + // printf("%s:%d: in func %s: free %p\n",file,line,func,p); +#ifdef MEMWATCH + mwFree(p,file,line); +#else + free(p); +#endif +} + +#elif defined(GCOLLECT) + +void * _bcallocA(size_t size, size_t cnt) { + void *ret = aMallocA(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +void * _bcalloc(size_t size, size_t cnt) { + void *ret = aMalloc(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +char * _bstrdup(const char *chr) { + int len = strlen(chr); + char *ret = (char*)aMalloc(len + 1); + strcpy(ret, chr); + return ret; +} + +#elif defined(USE_MEMMGR) + +/* USE_MEMMGR */ + +/* + * メモリマネージャ + * malloc , free の処理を効率的に出来るようにしたもの。 + * 複雑な処理を行っているので、若干重くなるかもしれません。 + * + * データ構造など(説明下手ですいません^^; ) + * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」 + * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分 + * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ + * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって + * 出来ていたりします。(padding,unit_head を除く) + * + * ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ + * ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな + * がっています。それにより、不要となったメモリの再利用が効率的に行えます。 + */ + +/* ブロックに入るデータ量 */ +#define BLOCK_DATA_SIZE 80*1024 + +/* 一度に確保するブロックの数。 */ +#define BLOCK_ALLOC 32 + +/* ブロックのアライメント */ +#define BLOCK_ALIGNMENT 64 + +/* ブロック */ +struct block { + int block_no; /* ブロック番号 */ + struct block* block_prev; /* 前に確保した領域 */ + struct block* block_next; /* 次に確保した領域 */ + int samesize_no; /* 同じサイズの番号 */ + struct block* samesize_prev; /* 同じサイズの前の領域 */ + struct block* samesize_next; /* 同じサイズの次の領域 */ + int unit_size; /* ユニットのバイト数 0=未使用 */ + int unit_hash; /* ユニットのハッシュ */ + int unit_count; /* ユニットの数 */ + int unit_used; /* 使用済みユニット */ + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block* block; + int size; + const char* file; + int line; +}; + +static struct block* block_first = NULL; +static struct block* block_last = NULL; +static struct block* block_unused = NULL; + +/* ユニットへのハッシュ。80KB/64Byte = 1280個 */ +static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最初 */ +static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 埋まってない */ +static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最後 */ + +/* メモリを使い回せない領域用のデータ */ +struct unit_head_large { + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; +}; +static struct unit_head_large *unit_head_large_first = NULL; + +static struct block* block_malloc(void); +static void block_free(struct block* p); +static void memmgr_info(void); + +void* aMalloc_(size_t size, const char *file, int line, const char *func ) { + int i; + struct block *block; + int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; + size = size_hash * BLOCK_ALIGNMENT; /* アライメントの倍数に切り上げ */ + + if(size == 0) { + return NULL; + } + + /* ブロック長を超える領域の確保には、malloc() を用いる */ + /* その際、unit_head.block に NULL を代入して区別する */ + if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { +#ifdef MEMWATCH + struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line); +#else + struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size); +#endif + if(p != NULL) { + p->unit_head.block = NULL; + p->unit_head.size = size; + p->unit_head.file = file; + p->unit_head.line = line; + if(unit_head_large_first == NULL) { + unit_head_large_first = p; + p->next = NULL; + p->prev = NULL; + } else { + unit_head_large_first->prev = p; + p->prev = NULL; + p->next = unit_head_large_first; + unit_head_large_first = p; + } + return (char *)p + sizeof(struct unit_head_large); + } else { + printf("MEMMGR::memmgr_alloc failed.\n"); + exit(1); + } + } + + /* 同一サイズのブロックが確保されていない時、新たに確保する */ + if(unit_unfill[size_hash] == NULL) { + block = block_malloc(); + if(unit_first[size_hash] == NULL) { + /* 初回確保 */ + unit_first[size_hash] = block; + unit_last[size_hash] = block; + block->samesize_no = 0; + block->samesize_prev = NULL; + block->samesize_next = NULL; + } else { + /* 連結作業 */ + unit_last[size_hash]->samesize_next = block; + block->samesize_no = unit_last[size_hash]->samesize_no + 1; + block->samesize_prev = unit_last[size_hash]; + block->samesize_next = NULL; + unit_last[size_hash] = block; + } + unit_unfill[size_hash] = block; + block->unit_size = size + sizeof(struct unit_head); + block->unit_count = BLOCK_DATA_SIZE / block->unit_size; + block->unit_used = 0; + block->unit_hash = size_hash; + /* 未使用Flagを立てる */ + for(i=0;i<block->unit_count;i++) { + ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; + } + } + /* ユニット使用個数加算 */ + block = unit_unfill[size_hash]; + block->unit_used++; + + /* ユニット内を全て使い果たした */ + if(block->unit_count == block->unit_used) { + do { + unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; + } while( + unit_unfill[size_hash] != NULL && + unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used + ); + } + + /* ブロックの中の空きユニット捜索 */ + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block == NULL) { + head->block = block; + head->size = size; + head->line = line; + head->file = file; + return (char *)head + sizeof(struct unit_head); + } + } + // ここに来てはいけない。 + printf("MEMMGR::memmgr_malloc() serious error.\n"); + memmgr_info(); + exit(1); + return NULL; +}; + +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) { + void *p = aMalloc_(num * size,file,line,func); + memset(p,0,num * size); + return p; +} + +void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) { + size_t old_size; + if(memblock == NULL) { + return aMalloc_(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size; + if(old_size > size) { + // サイズ縮小 -> そのまま返す(手抜き) + return memblock; + } else { + // サイズ拡大 + void *p = aMalloc_(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + aFree_(memblock,file,line,func); + return p; + } +} + +char* aStrdup_(const void *p, const char *file, int line, const char *func ) { + if(p == NULL) { + return NULL; + } else { + int len = strlen(p); + char *string = (char *)aMalloc_(len + 1,file,line,func); + memcpy(string,p,len+1); + return string; + } +} + +void aFree_(void *ptr, const char *file, int line, const char *func ) { + struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head)); + if(ptr == NULL) { + return; + } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + /* malloc() で直に確保された領域 */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large)); + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + free(head_large); + return; + } else { + /* ユニット解放 */ + struct block *block = head->block; + if(head->block == NULL) { + printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line); + } else { + head->block = NULL; + if(--block->unit_used == 0) { + /* ブロックの解放 */ + if(unit_unfill[block->unit_hash] == block) { + /* 空きユニットに指定されている */ + do { + unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next; + } while( + unit_unfill[block->unit_hash] != NULL && + unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used + ); + } + if(block->samesize_prev == NULL && block->samesize_next == NULL) { + /* 独立ブロックの解放 */ + unit_first[block->unit_hash] = NULL; + unit_last[block->unit_hash] = NULL; + unit_unfill[block->unit_hash] = NULL; + } else if(block->samesize_prev == NULL) { + /* 先頭ブロックの解放 */ + unit_first[block->unit_hash] = block->samesize_next; + (block->samesize_next)->samesize_prev = NULL; + } else if(block->samesize_next == NULL) { + /* 末端ブロックの解放 */ + unit_last[block->unit_hash] = block->samesize_prev; + (block->samesize_prev)->samesize_next = NULL; + } else { + /* 中間ブロックの解放 */ + (block->samesize_next)->samesize_prev = block->samesize_prev; + (block->samesize_prev)->samesize_next = block->samesize_next; + } + block_free(block); + } else { + /* 空きユニットの再設定 */ + if( + unit_unfill[block->unit_hash] == NULL || + unit_unfill[block->unit_hash]->samesize_no > block->samesize_no + ) { + unit_unfill[block->unit_hash] = block; + } + } + } + } +} + +/* 現在の状況を表示する */ +static void memmgr_info(void) { + int i; + struct block *p; + printf("** Memory Maneger Information **\n"); + if(block_first == NULL) { + printf("Uninitialized.\n"); + return; + } + printf( + "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n", + block_last->block_no+1,sizeof(struct block), + (block_last->block_no+1) * sizeof(struct block) / 1024 + ); + p = block_first; + for(i=0;i<=block_last->block_no;i++) { + printf(" Block #%04u : ",p->block_no); + if(p->unit_size == 0) { + printf("unused.\n"); + } else { + printf( + "size: %05u byte. used: %04u/%04u prev:", + p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count + ); + if(p->samesize_prev == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_prev)->block_no); + } + printf(" next:"); + if(p->samesize_next == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_next)->block_no); + } + printf("\n"); + } + p = p->block_next; + } +} + +/* ブロックを確保する */ +static struct block* block_malloc(void) { + if(block_unused != NULL) { + /* ブロック用の領域は確保済み */ + struct block* ret = block_unused; + do { + block_unused = block_unused->block_next; + } while(block_unused != NULL && block_unused->unit_size != 0); + return ret; + } else { + /* ブロック用の領域を新たに確保する */ + int i; + int block_no; + struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC); + if(p == NULL) { + printf("MEMMGR::block_alloc failed.\n"); + exit(1); + } + if(block_first == NULL) { + /* 初回確保 */ + block_no = 0; + block_first = p; + } else { + block_no = block_last->block_no + 1; + block_last->block_next = p; + p->block_prev = block_last; + } + block_last = &p[BLOCK_ALLOC - 1]; + /* ブロックを連結させる */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + p[i].block_prev = &p[i-1]; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + p[i].block_no = block_no + i; + } + + /* 未使用ブロックへのポインタを更新 */ + block_unused = &p[1]; + p->unit_size = 1; + return p; + } +} + +static void block_free(struct block* p) { + /* free() せずに、未使用フラグを付けるだけ */ + p->unit_size = 0; + /* 未使用ポインターを更新する */ + if(block_unused == NULL) { + block_unused = p; + } else if(block_unused->block_no > p->block_no) { + block_unused = p; + } +} + +static char memmer_logfile[128]; + +static FILE* memmgr_log(void) { + FILE *fp = fopen(memmer_logfile,"w"); + if(!fp) { fp = stdout; } + fprintf(fp,"memmgr: memory leaks found\n"); + return fp; +} + +static void memmer_exit(void) { + FILE *fp = NULL; + int i; + int count = 0; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + while(block) { + if(block->unit_size) { + if(!fp) { fp = memmgr_log(); } + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block != NULL) { + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + head->file,head->line,head->size + ); + } + } + } + block = block->block_next; + } + while(large) { + if(!fp) { fp = memmgr_log(); } + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + large->unit_head.file, + large->unit_head.line,large->unit_head.size + ); + large = large->next; + } + if(!fp) { + printf("memmgr: no memory leaks found.\n"); + } else { + printf("memmgr: memory leaks found.\n"); + fclose(fp); + } +} +#endif + +int do_init_memmgr(const char* file) { + #ifdef USE_MEMMGR + sprintf(memmer_logfile,"%s.log",file); + atexit(memmer_exit); + printf("memmgr: initialised: %s\n",memmer_logfile); + #endif + return 0; +} diff --git a/src/common/malloc.h b/src/common/malloc.h index 3733a5e55..c233adb8d 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -3,6 +3,49 @@ #include <stdlib.h> +#if defined(DMALLOC) + +# include "dmalloc.h" +# define aMalloc(size) \ + dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 0) +# define aMallocA(size) \ + dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 0) +# define aCallocA(count,size) \ + dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 0) +# define aCalloc(count,size) \ + dmalloc_malloc(__FILE__, __LINE__, (count)*(size), DMALLOC_FUNC_CALLOC, 0, 0) +# define aRealloc(ptr,size) \ + dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 0) +# define aFree(ptr) free(ptr) +# define aStrdup(ptr) strdup(ptr) + +#elif defined(GCOLLECT) + +# include "gc.h" +# define aMalloc(n) GC_MALLOC(n) +# define aMallocA(n) GC_MALLOC_ATOMIC(n) +# define aCallocA(m,n) _bcallocA(m,n) +# define aCalloc(m,n) _bcalloc(m,n) +# define aRealloc(p,n) GC_REALLOC(p,n) +# define aFree(n) GC_FREE(n) +# define aStrdup(n) _bstrdup(n) + + extern void * _bcalloc(size_t, size_t); + extern void * _bcallocA(size_t, size_t); + extern char * _bstrdup(const char *); + +#elif defined(BCHECK) + +# define aMalloc(n) malloc(n) +# define aMallocA(n) malloc(n) +# define aCalloc(m,n) calloc(m,n) +# define aCallocA(m,n) calloc(m,n) +# define aRealloc(p,n) realloc(p,n) +# define aFree(n) free(n) +# define aStrdup(n) strdup(n) + +#else + #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __func__ __FUNCTION__ @@ -11,15 +54,24 @@ # endif #endif -#define ALC_MARK __FILE__, __LINE__, __func__ +# define ALC_MARK __FILE__, __LINE__, __func__ -void* aMalloc_( size_t size, const char *file, int line, const char *func ); -void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ); -void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void* aMalloc_( size_t size, const char *file, int line, const char *func ); + void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ); + void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void aFree_( void *p, const char *file, int line, const char *func ); + char* aStrdup_( const void *p, const char *file, int line, const char *func ); -#define aMalloc(n) aMalloc_(n,ALC_MARK) -#define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) -#define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) +# define aMalloc(n) aMalloc_(n,ALC_MARK) +# define aMallocA(n) aMalloc_(n,ALC_MARK) +# define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) +# define aCallocA(m,n) aCalloc_(m,n,ALC_MARK) +# define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) +# define aStrdup(p) aStrdup_(p,ALC_MARK) +# define aFree(p) do { aFree_(p,ALC_MARK); if(p != NULL) { p = NULL; } } while(0) + +#endif +int do_init_memmgr(const char* file); #endif diff --git a/src/common/mmo.h b/src/common/mmo.h index f6150d39a..1602c5655 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -7,6 +7,20 @@ #include <time.h> #include "utils.h" // _WIN32 +#if ! defined(Assert) +#if defined(RELEASE) +#define Assert(EX) +#else +// extern "C" { +#include <assert.h> +// } +#if defined(_WIN32) +#include <crtdbg.h> +#endif +#define Assert(EX) assert(EX) +#endif +#endif /* ! defined(Assert) */ + #ifdef CYGWIN // txtやlogなどの書き出すファイルの改行コード #define RETCODE "\r\n" // (CR/LF:Windows系) @@ -29,7 +43,7 @@ #define MAX_AMOUNT 30000 #define MAX_ZENY 1000000000 // 1G zeny #define MAX_CART 100 -#define MAX_SKILL 450 +#define MAX_SKILL 650 #define GLOBAL_REG_NUM 96 #define ACCOUNT_REG_NUM 16 #define ACCOUNT_REG2_NUM 16 @@ -39,7 +53,7 @@ #define MAX_STORAGE 300 #define MAX_GUILD_STORAGE 1000 #define MAX_PARTY 12 -#define MAX_GUILD 36 // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW] +#define MAX_GUILD 16+10*6 // increased max guild members to accomodate for +6 increase for extension levels [Lupus] #define MAX_GUILDPOSITION 20 // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW] #define MAX_GUILDEXPLUSION 32 #define MAX_GUILDALLIANCE 16 @@ -54,8 +68,6 @@ #define MIN_CLOTH_COLOR battle_config.min_cloth_color #define MAX_CLOTH_COLOR battle_config.max_cloth_color -#define MIN_CHAR_ID 150000 // shouldn't ever be changed, the client requires this min value [Ajarn] - // for produce #define MIN_ATTRIBUTE 0 #define MAX_ATTRIBUTE 4 @@ -102,7 +114,7 @@ struct s_pet { int account_id; int char_id; int pet_id; - short class; + short class_; short level; short egg_id;//pet egg id short equip;//pet equip name_id @@ -117,10 +129,13 @@ struct mmo_charstatus { int char_id; int account_id; int partner_id; + int father; + int mother; + int child; int base_exp,job_exp,zeny; - short class; + short class_; short status_point,skill_point; int hp,max_hp,sp,max_sp; short option,karma,manner; @@ -131,7 +146,7 @@ struct mmo_charstatus { short head_top,head_mid,head_bottom; char name[24]; - unsigned char base_level,job_level; + unsigned int base_level,job_level; short str,agi,vit,int_,dex,luk; unsigned char char_num,sex; @@ -154,17 +169,18 @@ struct mmo_charstatus { }; struct storage { + int dirty; int account_id; short storage_status; short storage_amount; - struct item storage[MAX_STORAGE]; + struct item storage_[MAX_STORAGE]; }; struct guild_storage { int guild_id; short storage_status; short storage_amount; - struct item storage[MAX_GUILD_STORAGE]; + struct item storage_[MAX_GUILD_STORAGE]; }; struct map_session_data; @@ -185,13 +201,13 @@ struct party { int party_id; char name[24]; int exp; - int item; + int item, itemc; struct party_member member[MAX_PARTY]; }; struct guild_member { int account_id, char_id; - short hair,hair_color,gender,class,lv; + short hair,hair_color,gender,class_,lv; int exp,exp_payper; short online,position; int rsv1,rsv2; @@ -267,8 +283,8 @@ struct guild_castle { int Ghp4; int Ghp5; int Ghp6; - int Ghp7; - int GID0; + int Ghp7; + int GID0; int GID1; int GID2; int GID3; @@ -313,23 +329,25 @@ enum { GD_DEVELOPMENT=10014, }; -#ifndef _WIN32 -#ifndef strcmpi -#define strcmpi strcasecmp -#endif -#ifndef stricmp -#define stricmp strcasecmp -#endif -#ifndef strncmpi -#define strncmpi strncasecmp -#endif -#ifndef strnicmp -#define strnicmp strncasecmp -#endif -#ifndef strrchr -#define strrchr rindex -#endif - +#ifndef __WIN32 + #ifndef strcmpi + #define strcmpi strcasecmp + #endif + #ifndef stricmp + #define stricmp strcasecmp + #endif + #ifndef strncmpi + #define strncmpi strncasecmp + #endif + #ifndef strnicmp + #define strnicmp strncasecmp + #endif +#else + #define snprintf _snprintf + #define vsnprintf _vsnprintf + #ifndef strncmpi + #define strncmpi strnicmp + #endif #endif #endif // _MMO_H_ diff --git a/src/common/nullpo.h b/src/common/nullpo.h index 11283f941..0b9a9f7a5 100644 --- a/src/common/nullpo.h +++ b/src/common/nullpo.h @@ -87,6 +87,8 @@ #define nullpo_retr(ret, t) \ if (nullpo_chk(NLP_MARK, (void *)(t))) {return(ret);} +#define nullpo_retb(t) \ + if (nullpo_chk(NLP_MARK, (void *)(t))) {break;} // 可変引数マクロに関する条件コンパイル #if __STDC_VERSION__ >= 199901L @@ -100,6 +102,9 @@ #define nullpo_retr_f(ret, t, fmt, ...) \ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {return(ret);} +#define nullpo_retb_f(t, fmt, ...) \ + if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), __VA_ARGS__)) {break;} + #elif __GNUC__ >= 2 /* GCC用 */ #define nullpo_ret_f(t, fmt, args...) \ @@ -111,6 +116,9 @@ #define nullpo_retr_f(ret, t, fmt, args...) \ if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {return(ret);} +#define nullpo_retb_f(t, fmt, args...) \ + if (nullpo_chk_f(NLP_MARK, (void *)(t), (fmt), ## args)) {break;} + #else /* その他の場合・・・ orz */ @@ -127,6 +135,7 @@ #define nullpo_ret(t) if((t)){;} #define nullpo_retv(t) if((t)){;} #define nullpo_retr(ret, t) if((t)){;} +#define nullpo_retb(t) if((t)){;} // 可変引数マクロに関する条件コンパイル #if __STDC_VERSION__ >= 199901L @@ -134,12 +143,14 @@ #define nullpo_ret_f(t, fmt, ...) if((t)){;} #define nullpo_retv_f(t, fmt, ...) if((t)){;} #define nullpo_retr_f(ret, t, fmt, ...) if((t)){;} +#define nullpo_retb_f(t, fmt, ...) if((t)){;} #elif __GNUC__ >= 2 /* GCC用 */ #define nullpo_ret_f(t, fmt, args...) if((t)){;} #define nullpo_retv_f(t, fmt, args...) if((t)){;} #define nullpo_retr_f(ret, t, fmt, args...) if((t)){;} +#define nullpo_retb_f(t, fmt, args...) if((t)){;} #else /* その他の場合・・・ orz */ diff --git a/src/common/showmsg.c b/src/common/showmsg.c index b65181f3a..24d51d2dc 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -1,65 +1,68 @@ #include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <stdarg.h> #include "showmsg.h" char tmp_output[1024] = {"\0"}; -int _ShowMessage(const char *string, enum msg_type flag){ // by MC Cameri - /* - _ShowMessage MUST be used instead of printf as of 10/24/2004. - Return: 0 = Successful, 1 = Failed. - */ +// by MC Cameri +int _vShowMessage(enum msg_type flag, const char *string, va_list ap) +{ + // _ShowMessage MUST be used instead of printf as of 10/24/2004. + // Return: 0 = Successful, 1 = Failed. // int ret = 0; char prefix[40]; - char *output; - if (strlen(string) <= 0) { - ShowError("Empty string passed to ShowMessage().\n"); + + if (!string || strlen(string) <= 0) { + printf("Empty string passed to _ShowMessage().\n"); return 1; } switch (flag) { + case MSG_NONE: // direct printf replacement + break; case MSG_STATUS: //Bright Green (To inform about good things) - strcpy(prefix,"\033[1;32m[Status]\033[0;0m: "); + strcpy(prefix,CL_GREEN"[Status]"CL_RESET":"); break; -/* //Do we really need this now? [MC Cameri] case MSG_SQL: //Bright Violet (For dumping out anything related with SQL) - strcpy(prefix,"\033[1;35m[SQL]\033[0;0m: "); + strcpy(prefix,CL_MAGENTA"[SQL]"CL_RESET":"); break; -*/ - case MSG_INFORMATION: //Bright Blue (Variable information) - strcpy(prefix,"\033[1;34m[Info]\033[0;0m: "); + case MSG_INFORMATION: //Bright White (Variable information) + strcpy(prefix,CL_WHITE"[Info]"CL_RESET":"); break; case MSG_NOTICE: //Bright White (Less than a warning) - strcpy(prefix,"\033[1;29m[Notice]\033[0;0m: "); + strcpy(prefix,CL_WHITE"[Notice]"CL_RESET":"); break; case MSG_WARNING: //Bright Yellow - strcpy(prefix,"\033[1;33m[Warning]\033[0;0m: "); + strcpy(prefix,CL_YELLOW"[Warning]"CL_RESET":"); + break; + case MSG_DEBUG: //Bright Cyan, important stuff! + strcpy(prefix,CL_CYAN"[Debug]"CL_RESET":"); break; case MSG_ERROR: //Bright Red (Regular errors) - strcpy(prefix,"\033[1;31m[Error]\033[0;0m: "); + strcpy(prefix,CL_RED"[Error]"CL_RESET":"); break; case MSG_FATALERROR: //Bright Red (Fatal errors, abort(); if possible) - strcpy(prefix,"\033[1;31m[Fatal Error]\033[0;0m: "); + strcpy(prefix,CL_RED"[Fatal Error]"CL_RESET":"); break; default: - ShowError("In function _ShowMessage() -> Invalid flag passed.\n"); + printf("In function _ShowMessage() -> Invalid flag passed.\n"); return 1; } - output = (char*)malloc(sizeof(char)*(strlen(prefix)+strlen(string))+1); - if (output == NULL) { - return 1; -// abort(); // Kill server? + + if (!(flag == MSG_DEBUG && !SHOW_DEBUG_MSG)) { + if (flag != MSG_NONE) + printf ("%s ", prefix); + vprintf (string, ap); + fflush (stdout); } - strcpy(output,prefix); - strcat(output,string); - printf(output); - fflush(stdout); + + va_end(ap); /* if ((core_config.debug_output_level > -1) && (flag >= core_config.debug_output_level)) { FILE *fp; fp=fopen(OUTPUT_MESSAGES_LOG,"a"); if (fp == NULL) { - printf("\033[1;31m[Error]\033[0;0m: Could not open \033[1;29m%s\033[0;0m, file not found.\n",OUTPUT_MESSAGES_LOG); + printf(CL_RED"[Error]"CL_RESET": Could not open '"CL_WHITE"%s"CL_RESET"', file not found.\n",OUTPUT_MESSAGES_LOG); fflush(stdout); return; } @@ -71,3 +74,67 @@ int _ShowMessage(const char *string, enum msg_type flag){ // by MC Cameri */ return 0; } + +int _ShowMessage(enum msg_type flag, const char *string, ...) +{ + va_list ap; + + va_start(ap, string); + return _vShowMessage(flag, string, ap); +} + +// direct printf replacement +int ShowMessage(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_NONE, string, ap); +} +int ShowStatus(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_STATUS, string, ap); +} +int ShowSQL(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_SQL, string, ap); +} +int ShowInfo(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_INFORMATION, string, ap); +} +int ShowNotice(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_NOTICE, string, ap); +} +int ShowWarning(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_WARNING, string, ap); +} +int ShowDebug(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_DEBUG, string, ap); +} +int ShowError(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_ERROR, string, ap); +} +int ShowFatalError(const char *string, ...) { + va_list ap; + + va_start(ap, string); + return _vShowMessage(MSG_FATALERROR, string, ap); +} diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 1c4a2dfcb..b5f4d4bfd 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -1,50 +1,57 @@ #ifndef _SHOWMSG_H_ #define _SHOWMSG_H_ -extern char tmp_output[1024]; - -enum msg_type {MSG_STATUS,/* MSG_SQL, */MSG_INFORMATION,MSG_NOTICE,MSG_WARNING,MSG_ERROR,MSG_FATALERROR}; - -extern int _ShowMessage(const char *string, enum msg_type flag); - -/* MSG_XX */ - #define ShowMsg(string,flag) _ShowMessage(string,flag) -// #define DisplayMsg(string,flag) _ShowMessage(string,flag) - #define ShowMessage(string,flag) _ShowMessage(string,flag) - -/* MSG_STATUS */ - #define ShowStatus(string) _ShowMessage(string,MSG_STATUS) -// #define DisplayStatus(string) _ShowMessage(string,MSG_STATUS) - -/* MSG_SQL*/ -// #define ShowSQL(string) _ShowMessage(string,MSG_SQL) -// #define DisplaySQL(string) _ShowMessage(string,MSG_SQL) - -/* MSG_INFORMATION */ - #define ShowInfo(string) _ShowMessage(string,MSG_INFORMATION) -// #define DisplayInfo(string) _ShowMessage(string,MSG_INFORMATION) -// #define ShowInformation(string) _ShowMessage(string,MSG_INFORMATION) -// #define DisplayInformation(string) _ShowMessage(string,MSG_INFORMATION) - -/* MSG_NOTICE */ - #define ShowNotice(string) _ShowMessage(string,MSG_NOTICE) -// #define DisplayNotice(string) _ShowMessage(string,MSG_NOTICE) - -/* */ - #define ShowWarning(string) _ShowMessage(string,MSG_WARNING) -// #define DisplayWarning(string) _ShowMessage(string,MSG_WARNING) -// #define Warn(string) _ShowMessage(string,MSG_WARNING) +//davidsiaw, 'lookee' here! +#define SHOW_DEBUG_MSG 1 + +#ifdef _WIN32 +#define CL_RESET "" +#define CL_NORMAL CL_RESET +#define CL_NONE CL_RESET +#define CL_WHITE "" +#define CL_GRAY "" +#define CL_RED "" +#define CL_GREEN "" +#define CL_YELLOW "" +#define CL_BLUE "" +#define CL_MAGENTA "" +#define CL_CYAN "" +#else +#define CL_RESET "\033[0;0m" +#define CL_NORMAL CL_RESET +#define CL_NONE CL_RESET +#define CL_WHITE "\033[1;29m" +#define CL_GRAY "\033[1;30m" +#define CL_RED "\033[1;31m" +#define CL_GREEN "\033[1;32m" +#define CL_YELLOW "\033[1;33m" +#define CL_BLUE "\033[1;34m" +#define CL_MAGENTA "\033[1;35m" +#define CL_CYAN "\033[1;36m" +#endif -/* MSG_ERROR */ - #define ShowError(string) _ShowMessage(string,MSG_ERROR) -// #define DisplayError(string) _ShowMessage(string,MSG_ERROR) -// #define OutputError(string) _ShowMessage(string,MSG_ERROR) +extern char tmp_output[1024]; -/* MSG_FATALERROR */ - #define ShowFatalError(string) _ShowMessage(string,MSG_FATALERROR) -// #define DisplayFatalError(string) _ShowMessage(string,MSG_ERROR) -// #define Terminate(string) _ShowMessage(string,MSG_FATALERROR) -// #define Kill(string) _ShowMessage(string,MSG_FATALERROR) -// #define AbortEx(string) _ShowMessage(string,MSG_FATALERROR) +enum msg_type { + MSG_NONE, + MSG_STATUS, + MSG_SQL, + MSG_INFORMATION, + MSG_NOTICE, + MSG_WARNING, + MSG_DEBUG, + MSG_ERROR, + MSG_FATALERROR +}; + +extern int ShowMessage(const char *, ...); +extern int ShowStatus(const char *, ...); +extern int ShowSQL(const char *, ...); +extern int ShowInfo(const char *, ...); +extern int ShowNotice(const char *, ...); +extern int ShowWarning(const char *, ...); +extern int ShowDebug(const char *, ...); +extern int ShowError(const char *, ...); +extern int ShowFatalError(const char *, ...); #endif diff --git a/src/common/socket.c b/src/common/socket.c index 4afcf50d4..64f660a11 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -3,11 +3,14 @@ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> +#include <errno.h> #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> +#include <io.h> +typedef int socklen_t; #else #include <sys/socket.h> #include <netinet/in.h> @@ -16,14 +19,21 @@ #include <sys/time.h> #include <unistd.h> #include <sys/ioctl.h> + +#ifndef SIOCGIFCONF +#include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori] +#endif + #endif #include <fcntl.h> #include <string.h> -#include "mmo.h" // [Valaris] thanks to fov #include "socket.h" -#include "utils.h" +#include "../common/dll.h" +#include "../common/mmo.h" // [Valaris] thanks to fov +#include "../common/timer.h" +#include "../common/utils.h" #ifdef MEMWATCH #include "memwatch.h" @@ -31,6 +41,27 @@ fd_set readfds; int fd_max; +time_t tick_; +time_t stall_time_ = 60; +int ip_rules = 1; + +// #define UPNP + +#ifdef UPNP +#if defined(CYGWIN) || defined(_WIN32) +DLL upnp_dll; +int (*upnp_init)(); +int (*upnp_final)(); +int (*firewall_addport)(char *desc, int port); +int (*upnp_addport)(char *desc, char *ip, int port); +extern char *argp; + +int release_mappings = 1; +int close_ports = 1; +#else +#error This doesnt work with non-Windows yet +#endif +#endif int rfifo_size = 65536; int wfifo_size = 65536; @@ -39,6 +70,8 @@ int wfifo_size = 65536; #define TCP_FRAME_LEN 1053 #endif +#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24 + struct socket_data *session[FD_SETSIZE]; static int null_parse(int fd); @@ -46,6 +79,7 @@ static int (*default_func_parse)(int) = null_parse; static int null_console_parse(char *buf); static int (*default_console_parse)(char*) = null_console_parse; +static int connect_check(unsigned int ip); /*====================================== * CORE : Set function @@ -56,7 +90,10 @@ void set_defaultparse(int (*defaultparse)(int)) default_func_parse = defaultparse; } -#ifdef NSOCKET +void set_nonblocking(int fd, int yes) { + setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); +} + static void setsocketopts(int fd) { int yes = 1; // reuse fix @@ -65,13 +102,12 @@ static void setsocketopts(int fd) #ifdef SO_REUSEPORT setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); #endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); + set_nonblocking(fd, 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 )); } -#endif /* NSOCKET */ /*====================================== * CORE : Socket Sub Function *-------------------------------------- @@ -98,19 +134,10 @@ 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; + session[fd]->rdata_tick = tick_; } else if(len<=0){ // value of connection is not necessary the same -// if (fd == 4) // Removed [Yor] -// printf("Char-Server Has Disconnected.\n"); -// else if (fd == 5) // Removed [Yor] -// printf("Attempt To Log In Successful.\n"); -// else if (fd == 7) // Removed [Yor] -// printf("Char-Server Has Disconnected.\n"); -// else if (fd == 8) // Removed [Valaris] -// printf("%s has logged off your server.\n",RFIFOP(fd,6)); // Removed [Valaris] - -// else if (fd != 8) // [Valaris] - printf("set eof : connection #%d\n", fd); +// printf("set eof : connection #%d\n", fd); session[fd]->eof=1; } return 0; @@ -121,8 +148,10 @@ static int send_from_fifo(int fd) int len; //printf("send_from_fifo : %d\n",fd); - if(session[fd]->eof) + if(session[fd]->eof || session[fd]->wdata == 0) return -1; + if (session[fd]->wdata_size == 0) + return 0; #ifdef _WIN32 len=send(fd, session[fd]->wdata,session[fd]->wdata_size, 0); @@ -141,13 +170,22 @@ static int send_from_fifo(int fd) } else { session[fd]->wdata_size=0; } - } else { - printf("set eof :%d\n",fd); + } else if (errno != EAGAIN) { +// printf("set eof :%d\n",fd); session[fd]->eof=1; } return 0; } +void flush_fifos() +{ + int i; + for(i=0;i<fd_max;i++) + if(session[i] != NULL && + session[i]->func_send == send_from_fifo) + send_from_fifo(i); +} + static int null_parse(int fd) { printf("null_parse : %d\n",fd); @@ -165,45 +203,40 @@ static int connect_client(int listen_fd) int fd; struct sockaddr_in client_address; int len; +#ifndef _WIN32 int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ +#endif //printf("connect_client : %d\n",listen_fd); len=sizeof(client_address); - fd=accept(listen_fd,(struct sockaddr*)&client_address,&len); + fd = accept(listen_fd,(struct sockaddr*)&client_address,(socklen_t*)&len); if(fd_max<=fd) fd_max=fd+1; -#ifndef NSOCKET - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ setsocketopts(fd); -#endif /* NSOCKET */ - if(fd==-1) + if(fd==-1) { perror("accept"); - else + return -1; + } else if (ip_rules && !connect_check(*(unsigned int*)(&client_address.sin_addr))) { + close(fd); + return -1; + } else FD_SET(fd,&readfds); #ifdef _WIN32 - { - unsigned long val = 1; - ioctlsocket(fd, FIONBIO, &val); - } + { + unsigned long val = 1; + ioctlsocket(fd, FIONBIO, &val); + } #else result = fcntl(fd, F_SETFL, O_NONBLOCK); #endif CREATE(session[fd], struct socket_data, 1); - CREATE(session[fd]->rdata, char, rfifo_size); - CREATE(session[fd]->wdata, char, wfifo_size); + CREATE_A(session[fd]->rdata, unsigned char, rfifo_size); + CREATE_A(session[fd]->wdata, unsigned char, wfifo_size); session[fd]->max_rdata = rfifo_size; session[fd]->max_wdata = wfifo_size; @@ -211,6 +244,7 @@ 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]->rdata_tick = tick_; //printf("new_session : %d %d\n",fd,session[fd]->eof); return fd; @@ -221,9 +255,6 @@ int make_listen_port(int port) struct sockaddr_in server_address; int fd; int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ fd = socket( AF_INET, SOCK_STREAM, 0 ); if(fd_max<=fd) fd_max=fd+1; @@ -237,19 +268,11 @@ int make_listen_port(int port) result = fcntl(fd, F_SETFL, O_NONBLOCK); #endif -#ifndef NSOCKET - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ setsocketopts(fd); -#endif /* NSOCKET */ server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl( INADDR_ANY ); - server_address.sin_port = htons(port); + server_address.sin_port = htons((unsigned short)port); result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); if( result == -1 ) { @@ -276,16 +299,83 @@ int make_listen_port(int port) return fd; } +int make_listen_bind(long ip,int port) +{ + struct sockaddr_in server_address; + int fd; + int result; + + fd = socket( AF_INET, SOCK_STREAM, 0 ); + if(fd_max<=fd) fd_max=fd+1; + +#ifdef _WIN32 + { + unsigned long val = 1; + ioctlsocket(fd, FIONBIO, &val); + } +#else + result = fcntl(fd, F_SETFL, O_NONBLOCK); +#endif + + setsocketopts(fd); + + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = ip; + server_address.sin_port = htons((unsigned short)port); + +#ifdef UPNP + if (upnp_dll) { + int localaddr = ntohl(addr_[0]); + unsigned char *natip = (unsigned char *)&localaddr; + char buf[16]; + sprintf(buf, "%d.%d.%d.%d", natip[0], natip[1], natip[2], natip[3]); + //printf("natip=%d.%d.%d.%d\n", natip[0], natip[1], natip[2], natip[3]); + if (firewall_addport(argp, port)) + printf ("Firewall port %d successfully opened\n", port); + if (natip[0] == 192 && natip[1] == 168) { + if (upnp_addport(argp, natip, port)) + printf ("Upnp mappings successfull\n"); + else printf ("Upnp mapping failed\n"); + } + } +#endif + + result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address)); + if( result == -1 ) { + perror("bind"); + exit(1); + } + result = listen( fd, 5 ); + if( result == -1 ) { /* error */ + perror("listen"); + exit(1); + } + + FD_SET(fd, &readfds ); + + CREATE(session[fd], struct socket_data, 1); + + if(session[fd]==NULL){ + printf("out of memory : make_listen_bind\n"); + exit(1); + } + memset(session[fd],0,sizeof(*session[fd])); + session[fd]->func_recv = connect_client; + + return fd; +} + // Console Reciever [Wizputer] int console_recieve(int i) { int n; char *buf; - - CREATE(buf, char , 64); - + + CREATE_A(buf, char , 64); + memset(buf,0,sizeof(64)); n = read(0, buf , 64); + if ( n < 0 ) printf("Console input read error\n"); else @@ -307,48 +397,36 @@ static int null_console_parse(char *buf) // Console Input [Wizputer] int start_console(void) { FD_SET(0,&readfds); - + CREATE(session[0], struct socket_data, 1); if(session[0]==NULL){ printf("out of memory : start_console\n"); exit(1); } - + memset(session[0],0,sizeof(*session[0])); - + session[0]->func_recv = console_recieve; session[0]->func_console = default_console_parse; - + return 0; -} - +} + int make_connection(long ip,int port) { struct sockaddr_in server_address; int fd; int result; -#ifndef NSOCKET - int yes = 1; // reuse fix -#endif /* not NSOCKET */ fd = socket( AF_INET, SOCK_STREAM, 0 ); -#ifndef NSOCKET - if(fd_max<=fd) fd_max=fd+1; - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes); -#ifdef SO_REUSEPORT - setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes); -#endif - setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes); -#else /* NSOCKET */ - if(fd_max<=fd) + if(fd_max<=fd) fd_max=fd+1; setsocketopts(fd); -#endif /* NSOCKET */ server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = ip; - server_address.sin_port = htons(port); + server_address.sin_port = htons((unsigned short)port); #ifdef _WIN32 { @@ -364,31 +442,32 @@ int make_connection(long ip,int port) FD_SET(fd,&readfds); CREATE(session[fd], struct socket_data, 1); - CREATE(session[fd]->rdata, char, rfifo_size); - CREATE(session[fd]->wdata, char, wfifo_size); + CREATE_A(session[fd]->rdata, unsigned char, rfifo_size); + CREATE_A(session[fd]->wdata, unsigned char, wfifo_size); session[fd]->max_rdata = rfifo_size; session[fd]->max_wdata = wfifo_size; session[fd]->func_recv = recv_to_fifo; session[fd]->func_send = send_from_fifo; session[fd]->func_parse = default_func_parse; + session[fd]->rdata_tick = tick_; return fd; } int delete_session(int fd) { - if(fd<0 || fd>=FD_SETSIZE) + if(fd<=0 || fd>=FD_SETSIZE) return -1; FD_CLR(fd,&readfds); if(session[fd]){ if(session[fd]->rdata) - free(session[fd]->rdata); + aFree(session[fd]->rdata); if(session[fd]->wdata) - free(session[fd]->wdata); + aFree(session[fd]->wdata); if(session[fd]->session_data) - free(session[fd]->session_data); - free(session[fd]); + aFree(session[fd]->session_data); + aFree(session[fd]); } session[fd]=NULL; //printf("delete_session:%d\n",fd); @@ -397,13 +476,16 @@ int delete_session(int fd) int realloc_fifo(int fd,int rfifo_size,int wfifo_size) { - struct socket_data *s=session[fd]; + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if( s->max_rdata != rfifo_size && s->rdata_size < rfifo_size){ - RECREATE(s->rdata, char, rfifo_size); + RECREATE(s->rdata, unsigned char, rfifo_size); s->max_rdata = rfifo_size; } if( s->max_wdata != wfifo_size && s->wdata_size < wfifo_size){ - RECREATE(s->wdata, char, wfifo_size); + RECREATE(s->wdata, unsigned char, wfifo_size); s->max_wdata = wfifo_size; } return 0; @@ -411,11 +493,12 @@ int realloc_fifo(int fd,int rfifo_size,int wfifo_size) int WFIFOSET(int fd,int len) { - struct socket_data *s=session[fd]; -#ifdef NSOCKET + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if (s == NULL || s->wdata == NULL) return 0; -#endif /* NSOCKET */ if( s->wdata_size+len+16384 > s->max_wdata ){ unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; realloc_fifo(fd,s->max_rdata, s->max_wdata <<1 ); @@ -423,10 +506,8 @@ int WFIFOSET(int fd,int len) } s->wdata_size=(s->wdata_size+(len)+2048 < s->max_wdata) ? s->wdata_size+len : (printf("socket: %d wdata lost !!\n",fd),s->wdata_size); -#ifdef NSOCKET - if (s->wdata_size > (TCP_FRAME_LEN)) + if (s->wdata_size > (TCP_FRAME_LEN)) send_from_fifo(fd); -#endif /* NSOCKET */ return 0; } @@ -436,7 +517,10 @@ int do_sendrecv(int next) struct timeval timeout; int ret,i; - rfd=readfds; + tick_ = time(0); + + memcpy(&rfd, &readfds, sizeof(rfd)); + FD_ZERO(&wfd); for(i=0;i<fd_max;i++){ if(!session[i] && FD_ISSET(i,&readfds)){ @@ -460,13 +544,11 @@ int do_sendrecv(int next) if(FD_ISSET(i,&wfd)){ //printf("write:%d\n",i); if(session[i]->func_send) - //send_from_fifo(i); session[i]->func_send(i); } if(FD_ISSET(i,&rfd)){ //printf("read:%d\n",i); if(session[i]->func_recv) - //recv_to_fifo(i); session[i]->func_recv(i); } } @@ -479,6 +561,8 @@ int do_parsepacket(void) for(i=0;i<fd_max;i++){ if(!session[i]) continue; + if ((session[i]->rdata_tick != 0) && ((tick_ - session[i]->rdata_tick) > stall_time_)) + session[i]->eof = 1; if(session[i]->rdata_size==0 && session[i]->eof==0) continue; if(session[i]->func_parse){ @@ -491,14 +575,306 @@ int do_parsepacket(void) return 0; } -void do_socket(void) +/* DDoS 攻撃対策 */ + +enum { + ACO_DENY_ALLOW=0, + ACO_ALLOW_DENY, + ACO_MUTUAL_FAILTURE, +}; + +struct _access_control { + unsigned int ip; + unsigned int mask; +}; + +static struct _access_control *access_allow; +static struct _access_control *access_deny; +static int access_order=ACO_DENY_ALLOW; +static int access_allownum=0; +static int access_denynum=0; +static int access_debug=0; +static int ddos_count = 10; +static int ddos_interval = 3000; +static int ddos_autoreset = 600*1000; + +struct _connect_history { + struct _connect_history *next; + struct _connect_history *prev; + int status; + int count; + unsigned int ip; + unsigned int tick; +}; +static struct _connect_history *connect_history[0x10000]; +static int connect_check_(unsigned int ip); + +// 接続できるかどうかの確認 +// false : 接続OK +// true : 接続NG +static int connect_check(unsigned int ip) { + int result = connect_check_(ip); + if(access_debug) { + printf("connect_check: Connection from %d.%d.%d.%d %s\n", + CONVIP(ip),result ? "allowed." : "denied!"); + } + return result; +} + +static int connect_check_(unsigned int ip) { + struct _connect_history *hist = connect_history[ip & 0xFFFF]; + struct _connect_history *hist_new; + int i,is_allowip = 0,is_denyip = 0,connect_ok = 0; + + // allow , deny リストに入っているか確認 + for(i = 0;i < access_allownum; i++) { + if((ip & access_allow[i].mask) == (access_allow[i].ip & access_allow[i].mask)) { + if(access_debug) { + printf("connect_check: Found match from allow list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", + CONVIP(ip), + CONVIP(access_allow[i].ip), + CONVIP(access_allow[i].mask)); + } + is_allowip = 1; + break; + } + } + for(i = 0;i < access_denynum; i++) { + if((ip & access_deny[i].mask) == (access_deny[i].ip & access_deny[i].mask)) { + if(access_debug) { + printf("connect_check: Found match from deny list:%d.%d.%d.%d IP:%d.%d.%d.%d Mask:%d.%d.%d.%d\n", + CONVIP(ip), + CONVIP(access_deny[i].ip), + CONVIP(access_deny[i].mask)); + } + is_denyip = 1; + break; + } + } + // コネクト出来るかどうか確認 + // connect_ok + // 0 : 無条件に拒否 + // 1 : 田代砲チェックの結果次第 + // 2 : 無条件に許可 + switch(access_order) { + case ACO_DENY_ALLOW: + default: + if(is_allowip) { + connect_ok = 2; + } else if(is_denyip) { + connect_ok = 0; + } else { + connect_ok = 1; + } + break; + case ACO_ALLOW_DENY: + if(is_denyip) { + connect_ok = 0; + } else if(is_allowip) { + connect_ok = 2; + } else { + connect_ok = 1; + } + break; + case ACO_MUTUAL_FAILTURE: + if(is_allowip) { + connect_ok = 2; + } else { + connect_ok = 0; + } + break; + } + + // 接続履歴を調べる + while(hist) { + if(ip == hist->ip) { + // 同じIP発見 + if(hist->status) { + // ban フラグが立ってる + return (connect_ok == 2 ? 1 : 0); + } else if(DIFF_TICK(gettick(),hist->tick) < ddos_interval) { + // ddos_interval秒以内にリクエスト有り + hist->tick = gettick(); + if(hist->count++ >= ddos_count) { + // ddos 攻撃を検出 + hist->status = 1; + printf("connect_check: DDOS Attack detected from %d.%d.%d.%d!\n", + CONVIP(ip)); + return (connect_ok == 2 ? 1 : 0); + } else { + return connect_ok; + } + } else { + // ddos_interval秒以内にリクエスト無いのでタイマークリア + hist->tick = gettick(); + hist->count = 0; + return connect_ok; + } + } + hist = hist->next; + } + // IPリストに無いので新規作成 + hist_new = (struct _connect_history *) aCalloc(1,sizeof(struct _connect_history)); + hist_new->ip = ip; + hist_new->tick = gettick(); + if(connect_history[ip & 0xFFFF] != NULL) { + hist = connect_history[ip & 0xFFFF]; + hist->prev = hist_new; + hist_new->next = hist; + } + connect_history[ip & 0xFFFF] = hist_new; + return connect_ok; +} + +static int connect_check_clear(int tid,unsigned int tick,int id,int data) { + int i; + int clear = 0; + int list = 0; + struct _connect_history *hist , *hist2; + for(i = 0;i < 0x10000 ; i++) { + hist = connect_history[i]; + while(hist) { + if( + (DIFF_TICK(tick,hist->tick) > ddos_interval * 3 && !hist->status) || + (DIFF_TICK(tick,hist->tick) > ddos_autoreset && hist->status) + ) { + // clear data + hist2 = hist->next; + if(hist->prev) { + hist->prev->next = hist->next; + } else { + connect_history[i] = hist->next; + } + if(hist->next) { + hist->next->prev = hist->prev; + } + aFree(hist); + hist = hist2; + clear++; + } else { + hist = hist->next; + list++; + } + } + } + if(access_debug) { + printf("connect_check_clear: Cleared %d of %d from IP list.\n", clear, clear+list); + } + return list; +} + +// IPマスクチェック +int access_ipmask(const char *str,struct _access_control* acc) { - FD_ZERO(&readfds); + unsigned int mask=0,i=0,m,ip, a0,a1,a2,a3; + if( !strcmp(str,"all") ) { + ip = 0; + mask = 0; + } else { + if( sscanf(str,"%d.%d.%d.%d%n",&a0,&a1,&a2,&a3,&i)!=4 || i==0) { + printf("access_ipmask: Unknown format %s!\n",str); + return 0; + } + ip = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0; + + if(sscanf(str+i,"/%d.%d.%d.%d",&a0,&a1,&a2,&a3)==4 ){ + mask = (a3 << 24) | (a2 << 16) | (a1 << 8) | a0; + } else if(sscanf(str+i,"/%d",&m) == 1) { + for(i=0;i<m;i++) { + mask = (mask >> 1) | 0x80000000; + } + mask = ntohl(mask); + } else { + mask = 0xFFFFFFFF; + } + } + if(access_debug) { + printf("access_ipmask: Loaded IP:%d.%d.%d.%d mask:%d.%d.%d.%d\n", + CONVIP(ip), CONVIP(mask)); + } + acc->ip = ip; + acc->mask = mask; + return 1; +} + +int socket_config_read(const char *cfgName) { + int i; + char line[1024],w1[1024],w2[1024]; + FILE *fp; + + fp=fopen(cfgName, "r"); + if(fp==NULL){ + printf("File not found: %s\n", cfgName); + return 1; + } + while(fgets(line,1020,fp)){ + if(line[0] == '/' && line[1] == '/') + continue; + i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); + if(i!=2) + continue; + if(strcmpi(w1,"stall_time")==0){ + stall_time_ = atoi(w2); + } else if(strcmpi(w1,"enable_ip_rules")==0){ + if(strcmpi(w2,"yes")==0) + ip_rules = 1; + else if(strcmpi(w2,"no")==0) + ip_rules = 0; + else ip_rules = atoi(w2); + } else if(strcmpi(w1,"order")==0){ + access_order=atoi(w2); + if(strcmpi(w2,"deny,allow")==0) access_order=ACO_DENY_ALLOW; + if(strcmpi(w2,"allow,deny")==0) access_order=ACO_ALLOW_DENY; + if(strcmpi(w2,"mutual-failure")==0) access_order=ACO_MUTUAL_FAILTURE; + } else if(strcmpi(w1,"allow")==0){ + access_allow = (struct _access_control *) aRealloc(access_allow,(access_allownum+1)*sizeof(struct _access_control)); + if(access_ipmask(w2,&access_allow[access_allownum])) { + access_allownum++; + } + } else if(strcmpi(w1,"deny")==0){ + access_deny = (struct _access_control *) aRealloc(access_deny,(access_denynum+1)*sizeof(struct _access_control)); + if(access_ipmask(w2,&access_deny[access_denynum])) { + access_denynum++; + } + } else if(!strcmpi(w1,"ddos_interval")){ + ddos_interval = atoi(w2); + } else if(!strcmpi(w1,"ddos_count")){ + ddos_count = atoi(w2); + } else if(!strcmpi(w1,"ddos_autoreset")){ + ddos_autoreset = atoi(w2); + } else if(!strcmpi(w1,"debug")){ + if(strcmpi(w2,"yes")==0) + access_debug = 1; + else if(strcmpi(w2,"no")==0) + access_debug = 0; + else access_debug = atoi(w2); + #ifdef UPNP + } else if(!strcmpi(w1,"release_mappings")){ + if(strcmpi(w2,"yes")==0) + release_mappings = 1; + else if(strcmpi(w2,"no")==0) + release_mappings = 0; + else release_mappings = atoi(w2); + } else if(!strcmpi(w1,"close_ports")){ + if(strcmpi(w2,"yes")==0) + close_ports = 1; + else if(strcmpi(w2,"no")==0) + close_ports = 0; + else close_ports = atoi(w2); + #endif + } else if (strcmpi(w1, "import") == 0) + socket_config_read(w2); + } + fclose(fp); + return 0; } int RFIFOSKIP(int fd,int len) { - struct socket_data *s=session[fd]; + struct socket_data *s; + + if (fd <= 0) return 0; + s = session[fd]; if (s->rdata_size-s->rdata_pos-len<0) { fprintf(stderr,"too many skip\n"); @@ -521,7 +897,7 @@ int Net_Init(void) unsigned int i; char fullhost[255]; struct hostent* hent; - + /* Start up the windows networking */ WSADATA wsaData; @@ -533,7 +909,7 @@ int Net_Init(void) if(gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) { printf("Ugg.. no hostname defined!\n"); return 0; - } + } // XXX This should look up the local IP addresses in the registry // instead of calling gethostbyname. However, the way IP addresses @@ -566,7 +942,7 @@ int Net_Init(void) return 0; } - for(pos = 0; pos < ic.ifc_len;) + for(pos = 0; pos < ic.ifc_len;) { struct ifreq * ir = (struct ifreq *) (ic.ifc_buf + pos); @@ -593,3 +969,101 @@ int Net_Init(void) return(0); } + +#ifdef UPNP +// not implemented yet ^^; +void do_init_upnp(void) +{ + int *_release_mappings; + int *_close_ports; + + upnp_dll = DLL_OPEN ("upnp.dll"); + if (!upnp_dll) { + printf ("Cannot open upnp.dll: %s\n", dlerror()); + return; + } + DLL_SYM (upnp_init, upnp_dll, "do_init"); + DLL_SYM (upnp_final, upnp_dll, "do_final"); + DLL_SYM (firewall_addport, upnp_dll, "Firewall_AddPort"); + DLL_SYM (upnp_addport, upnp_dll, "UPNP_AddPort"); + if (!upnp_init || !upnp_final || !firewall_addport || !upnp_addport) { + printf ("Cannot load symbol: %s\n", dlerror()); + DLL_CLOSE (upnp_dll); + upnp_dll = NULL; + return; + } + + DLL_SYM (_release_mappings, upnp_dll, "release_mappings"); + DLL_SYM (_close_ports, upnp_dll, "close_ports"); + if (release_mappings && _release_mappings) + *_release_mappings = release_mappings; + if (close_ports && _close_ports) + *_close_ports = close_ports; + + if (upnp_init() == 0) { + printf ("Error initialising upnp.dll, unloading...\n"); + DLL_CLOSE (upnp_dll); + upnp_dll = NULL; + } + return; +} +#endif + +void do_final_socket(void) +{ + int i; + struct _connect_history *hist , *hist2; + for(i=0; i<fd_max; i++) { + if(session[i]) { + delete_session(i); + } + } + for(i=0; i<0x10000; i++) { + hist = connect_history[i]; + while(hist) { + hist2 = hist->next; + aFree(hist); + hist = hist2; + } + } + if (access_allow) + aFree(access_allow); + if (access_deny) + aFree(access_deny); + + // session[0] のダミーデータを削除 + aFree(session[0]->rdata); + aFree(session[0]->wdata); + aFree(session[0]); + +#ifdef UPNP + if (upnp_dll) { + upnp_final(); + DLL_CLOSE(upnp_dll); + } +#endif +} + +void do_socket(void) +{ + char *SOCKET_CONF_FILENAME = "conf/packet_athena.conf"; + + FD_ZERO(&readfds); + + atexit(do_final_socket); + socket_config_read(SOCKET_CONF_FILENAME); + + // session[0] にダミーデータを確保する + CREATE(session[0], struct socket_data, 1); + CREATE_A(session[0]->rdata, unsigned char, rfifo_size); + CREATE_A(session[0]->wdata, unsigned char, wfifo_size); + session[0]->max_rdata = rfifo_size; + session[0]->max_wdata = wfifo_size; + + // とりあえず5分ごとに不要なデータを削除する + add_timer_interval(gettick()+1000,connect_check_clear,0,0,300*1000); + +#ifdef UPNP + do_init_upnp(); +#endif +} diff --git a/src/common/socket.h b/src/common/socket.h index e3ad0826a..37d41203e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -5,24 +5,31 @@ #include <stdio.h> -#ifdef _WIN32 +#ifdef __WIN32 #include <winsock.h> #else #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #endif +#include <time.h> +#include "malloc.h" + +extern time_t tick_; +extern time_t stall_time_; // define declaration +#define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size) #define RFIFOP(fd,pos) (session[fd]->rdata+session[fd]->rdata_pos+(pos)) -#define RFIFOB(fd,pos) (*(unsigned char*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -#define RFIFOW(fd,pos) (*(unsigned short*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -#define RFIFOL(fd,pos) (*(unsigned int*)(session[fd]->rdata+session[fd]->rdata_pos+(pos))) -//#define RFIFOSKIP(fd,len) ((session[fd]->rdata_size-session[fd]->rdata_pos-(len)<0) ? (fprintf(stderr,"too many skip\n"),exit(1)) : (session[fd]->rdata_pos+=(len))) -#define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos) +// use function instead of macro. +#define RFIFOB(fd,pos) (*(unsigned char*)RFIFOP(fd,pos)) +#define RFIFOW(fd,pos) (*(unsigned short*)RFIFOP(fd,pos)) +#define RFIFOL(fd,pos) (*(unsigned int*)RFIFOP(fd,pos)) +#define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos) #define RFIFOFLUSH(fd) (memmove(session[fd]->rdata,RFIFOP(fd,0),RFIFOREST(fd)),session[fd]->rdata_size=RFIFOREST(fd),session[fd]->rdata_pos=0) -#define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size) +//#define RFIFOSKIP(fd,len) ((session[fd]->rdata_size-session[fd]->rdata_pos-(len)<0) ? (fprintf(stderr,"too many skip\n"),exit(1)) : (session[fd]->rdata_pos+=(len))) + #define RBUFP(p,pos) (((unsigned char*)(p))+(pos)) #define RBUFB(p,pos) (*(unsigned char*)RBUFP((p),(pos))) #define RBUFW(p,pos) (*(unsigned short*)RBUFP((p),(pos))) @@ -30,9 +37,9 @@ #define WFIFOSPACE(fd) (session[fd]->max_wdata-session[fd]->wdata_size) #define WFIFOP(fd,pos) (session[fd]->wdata+session[fd]->wdata_size+(pos)) -#define WFIFOB(fd,pos) (*(unsigned char*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) -#define WFIFOW(fd,pos) (*(unsigned short*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) -#define WFIFOL(fd,pos) (*(unsigned int*)(session[fd]->wdata+session[fd]->wdata_size+(pos))) +#define WFIFOB(fd,pos) (*(unsigned char*)WFIFOP(fd,pos)) +#define WFIFOW(fd,pos) (*(unsigned short*)WFIFOP(fd,pos)) +#define WFIFOL(fd,pos) (*(unsigned int*)WFIFOP(fd,pos)) // use function instead of macro. //#define WFIFOSET(fd,len) (session[fd]->wdata_size = (session[fd]->wdata_size+(len)+2048 < session[fd]->max_wdata) ? session[fd]->wdata_size+len : session[fd]->wdata_size) #define WBUFP(p,pos) (((unsigned char*)(p))+(pos)) @@ -54,6 +61,7 @@ struct socket_data{ unsigned char *rdata,*wdata; int max_rdata,max_wdata; int rdata_size,wdata_size; + time_t rdata_tick; int rdata_pos; struct sockaddr_in client_addr; int (*func_recv)(int); @@ -80,6 +88,7 @@ extern int fd_max; // Function prototype declaration int make_listen_port(int); +int make_listen_bind(long,int); int make_connection(long,int); int delete_session(int); int realloc_fifo(int fd,int rfifo_size,int wfifo_size); @@ -90,6 +99,9 @@ int do_sendrecv(int next); int do_parsepacket(void); void do_socket(void); +extern void flush_fifos(); +extern void set_nonblocking(int fd, int yes); + int start_console(void); void set_defaultparse(int (*defaultparse)(int)); diff --git a/src/common/strlib.c b/src/common/strlib.c new file mode 100644 index 000000000..2b130e76d --- /dev/null +++ b/src/common/strlib.c @@ -0,0 +1,98 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "strlib.h" +#include "utils.h" +#include "malloc.h" + +//----------------------------------------------- +// string lib. +char* jstrescape (char* pt) { + //copy from here + char *ptr; + int i =0, j=0; + + //copy string to temporary + CREATE_A(ptr, char, J_MAX_MALLOC_SIZE); + strcpy(ptr,pt); + + while (ptr[i] != '\0') { + switch (ptr[i]) { + case '\'': + pt[j++] = '\\'; + pt[j++] = ptr[i++]; + break; + case '\\': + pt[j++] = '\\'; + pt[j++] = ptr[i++]; + break; + default: + pt[j++] = ptr[i++]; + } + } + pt[j++] = '\0'; + aFree (ptr); + return &pt[0]; +} + +char* jstrescapecpy (char* pt,char* spt) { + //copy from here + int i =0, j=0; + + while (spt[i] != '\0') { + switch (spt[i]) { + case '\'': + pt[j++] = '\\'; + pt[j++] = spt[i++]; + break; + case '\\': + pt[j++] = '\\'; + pt[j++] = spt[i++]; + break; + default: + pt[j++] = spt[i++]; + } + } + pt[j++] = '\0'; + return &pt[0]; +} +int jmemescapecpy (char* pt,char* spt, int size) { + //copy from here + int i =0, j=0; + + while (i < size) { + switch (spt[i]) { + case '\'': + pt[j++] = '\\'; + pt[j++] = spt[i++]; + break; + case '\\': + pt[j++] = '\\'; + pt[j++] = spt[i++]; + break; + default: + pt[j++] = spt[i++]; + } + } + // copy size is 0 ~ (j-1) + return j; +} + +//----------------------------------------------------- +// Function to suppress control characters in a string. +//----------------------------------------------------- +//int remove_control_chars(char *str) { +int remove_control_chars(unsigned char *str) { + int i; + int change = 0; + + for(i = 0; str[i]; i++) { + if (str[i] < 32) { + str[i] = '_'; + change = 1; + } + } + + return change; +} diff --git a/src/common/strlib.h b/src/common/strlib.h new file mode 100644 index 000000000..55920f823 --- /dev/null +++ b/src/common/strlib.h @@ -0,0 +1,13 @@ +#ifndef _J_STR_LIB_H_ +#define _J_STR_LIB_H_ +#define J_MAX_MALLOC_SIZE 65535 +// String function library. +// code by Jioh L. Jung (ziozzang@4wish.net) +// This code is under license "BSD" +char* jstrescape (char* pt); +char* jstrescapecpy (char* pt,char* spt); +int jmemescapecpy (char* pt,char* spt, int size); + +// custom functions +int remove_control_chars(unsigned char *); +#endif diff --git a/src/common/timer.c b/src/common/timer.c index 97c162e7f..6a740d47a 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -1,37 +1,34 @@ -// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $ +// $Id: timer.c,v 1.1.1.1 2004/09/10 17:44:49 Yor Exp $ // original : core.c 2003/02/26 18:03:12 Rev 1.7 +//#include <config.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> -#ifdef _WIN32 -#include <winsock.h> +#ifdef __WIN32 +#define __USE_W32_SOCKETS +#include <windows.h> #else #include <sys/socket.h> #include <sys/time.h> #endif #include "timer.h" -#include "utils.h" +#include "malloc.h" #ifdef MEMWATCH #include "memwatch.h" #endif -// If the server shows no reaction when processing thousands of monsters - -// or connected by many clients, please increase TIMER_MIN_INTERVEL. - -#define TIMER_MIN_INTERVEL 50 - static struct TimerData* timer_data; -static int timer_data_max,timer_data_num; +static int timer_data_max, timer_data_num; static int* free_timer_list; static int free_timer_list_max, free_timer_list_pos; -static int timer_heap_max=0; //fixed Shinomori from eA forums +static int timer_heap_num = 0, timer_heap_max = 0; static int* timer_heap = NULL; // for debug @@ -42,38 +39,37 @@ struct timer_func_list { }; static struct timer_func_list* tfl_root; -#if defined(_WIN32) -void gettimeofday(struct timeval *t, struct timezone *dummy) -{ - DWORD millisec = GetTickCount(); +#ifdef __WIN32 +/* Modified struct timezone to void - we pass NULL anyway */ +void gettimeofday(struct timeval *t, void *dummy) { + DWORD millisec = GetTickCount(); - t->tv_sec = (int) (millisec / 1000); - t->tv_usec = (millisec % 1000) * 1000; + t->tv_sec = (int) (millisec / 1000); + t->tv_usec = (millisec % 1000) * 1000; } - #endif - // -int add_timer_func_list(int (*func)(int,unsigned int,int,int),char* name) -{ +int add_timer_func_list(int (*func)(int,unsigned int,int,int), char* name) { struct timer_func_list* tfl; - CREATE(tfl, struct timer_func_list, 1); - CREATE(tfl->name, char, strlen(name) + 1); + //CALLOC(tfl, struct timer_func_list, 1); + tfl = (struct timer_func_list*) aCalloc( sizeof(struct timer_func_list) , 1); + //MALLOC(tfl->name, char, strlen(name) + 1); + tfl->name = (char *) aMalloc( strlen(name) + 1 ); tfl->next = tfl_root; tfl->func = func; - strcpy(tfl->name,name); + strcpy(tfl->name, name); tfl_root = tfl; return 0; } -char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) -{ +char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) { struct timer_func_list* tfl; - for(tfl = tfl_root;tfl;tfl = tfl->next) { + + for(tfl = tfl_root; tfl; tfl = tfl->next) { if (func == tfl->func) return tfl->name; } @@ -85,19 +81,21 @@ char* search_timer_func_list(int (*func)(int,unsigned int,int,int)) *----------------------------*/ static unsigned int gettick_cache; static int gettick_count; -unsigned int gettick_nocache(void) -{ + +unsigned int gettick_nocache(void) { struct timeval tval; - gettimeofday(&tval,NULL); + + gettimeofday(&tval, NULL); gettick_count = 256; - return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec/1000; + + return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000; } -unsigned int gettick(void) -{ +unsigned int gettick(void) { gettick_count--; - if (gettick_count<0) + if (gettick_count < 0) return gettick_nocache(); + return gettick_cache; } @@ -105,71 +103,66 @@ unsigned int gettick(void) * CORE : Timer Heap *-------------------------------------- */ -static void push_timer_heap(int index) -{ - int i, h; - - if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max) { - int first = timer_heap == NULL; - - timer_heap_max += 256; - RECREATE(timer_heap, int, timer_heap_max); - memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256); - if (first) - timer_heap[0] = 0; - } - - timer_heap[0]++; - - for (h = timer_heap[0]-1, i = (h - 1) / 2; - h > 0 && DIFF_TICK(timer_data[index].tick, - timer_data[timer_heap[i + 1]].tick) < 0; - i = (h - 1) / 2) { - timer_heap[h + 1] = timer_heap[i + 1]; - h = i; - } - timer_heap[h + 1] = index; -} - -static int top_timer_heap() -{ - if (timer_heap == NULL || timer_heap[0] <= 0) - return -1; - - return timer_heap[1]; -} - -static int pop_timer_heap() -{ - int i,h,k; - int ret,last; - - if (timer_heap == NULL || timer_heap[0] <= 0) - return -1; - ret = timer_heap[1]; - last = timer_heap[timer_heap[0]]; - timer_heap[0]--; - - for(h = 0,k = 2;k<timer_heap[0];k = k * 2 + 2) { - if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick , timer_data[timer_heap[k]].tick)>0) - k--; - timer_heap[h + 1] = timer_heap[k + 1], h = k; +static void push_timer_heap(int index) { + int i, j; + int min, max, pivot; // for sorting + + // check number of element + if (timer_heap_num >= timer_heap_max) { + if (timer_heap_max == 0) { + timer_heap_max = 256; + //CALLOC(timer_heap, int, 256); + timer_heap = (int *) aCalloc( sizeof(int) , 256); + } else { + timer_heap_max += 256; + //REALLOC(timer_heap, int, timer_heap_max); + timer_heap = (int *) aRealloc( timer_heap, sizeof(int) * timer_heap_max); + memset(timer_heap + (timer_heap_max - 256), 0, sizeof(int) * 256); + } } - if (k == timer_heap[0]) - timer_heap[h + 1] = timer_heap[k], h = k-1; - for(i = (h-1)/2; - h>0 && DIFF_TICK(timer_data[timer_heap[i + 1]].tick , timer_data[last].tick)>0; - i = (h-1)/2) { - timer_heap[h + 1] = timer_heap[i + 1],h = i; + // do a sorting from higher to lower + j = timer_data[index].tick; // speed up + // with less than 4 values, it's speeder to use simple loop + if (timer_heap_num < 4) { + for(i = timer_heap_num; i > 0; i--) + if (j < timer_data[timer_heap[i - 1]].tick) + break; + else + timer_heap[i] = timer_heap[i - 1]; + timer_heap[i] = index; + // searching by dichotomie + } else { + // if lower actual item is higher than new + if (j < timer_data[timer_heap[timer_heap_num - 1]].tick) + timer_heap[timer_heap_num] = index; + else { + // searching position + min = 0; + max = timer_heap_num - 1; + while (min < max) { + pivot = (min + max) / 2; + if (j < timer_data[timer_heap[pivot]].tick) + min = pivot + 1; + else + max = pivot; + } + // move elements - do loop if there are a little number of elements to move + if (timer_heap_num - min < 5) { + for(i = timer_heap_num; i > min; i--) + timer_heap[i] = timer_heap[i - 1]; + // move elements - else use memmove (speeder for a lot of elements) + } else + memmove(&timer_heap[min + 1], &timer_heap[min], sizeof(int) * (timer_heap_num - min)); + // save new element + timer_heap[min] = index; + } } - timer_heap[h + 1] = last; - return ret; + timer_heap_num++; } -int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data) -{ +int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data) { struct TimerData* td; int i; @@ -180,24 +173,18 @@ int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int } else i = timer_data_num; if (i >= timer_data_num) - for (i = timer_data_num;i<timer_data_max && timer_data[i].type; i++); + for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++); if (i >= timer_data_num && i >= timer_data_max) { - int j; if (timer_data_max == 0) { timer_data_max = 256; - CREATE(timer_data, struct TimerData, timer_data_max); + //CALLOC(timer_data, struct TimerData, timer_data_max); + timer_data = (struct TimerData*) aCalloc( sizeof(struct TimerData) , timer_data_max); } else { timer_data_max += 256; - RECREATE(timer_data, struct TimerData, timer_data_max); - if (timer_data == NULL) { - printf("out of memory : add_timer timer_data\n"); - exit(1); - } - memset(timer_data + (timer_data_max - 256), 0, - sizeof(struct TimerData) * 256); + //REALLOC(timer_data, struct TimerData, timer_data_max); + timer_data = (struct TimerData *) aRealloc( timer_data, sizeof(struct TimerData) * timer_data_max); + memset(timer_data + (timer_data_max - 256), 0, sizeof(struct TimerData) * 256); } - for(j = timer_data_max-256;j<timer_data_max; j++) - timer_data[j].type = 0; } td = &timer_data[i]; td->tick = tick; @@ -209,88 +196,79 @@ int add_timer(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int push_timer_heap(i); if (i >= timer_data_num) timer_data_num = i + 1; + return i; } -int add_timer_interval(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data,int interval) -{ +int add_timer_interval(unsigned int tick,int (*func)(int,unsigned int,int,int),int id,int data,int interval) { int tid; + tid = add_timer(tick,func,id,data); timer_data[tid].type = TIMER_INTERVAL; timer_data[tid].interval = interval; + return tid; } -int delete_timer(int id,int (*func)(int,unsigned int,int,int)) -{ +int delete_timer(int id,int (*func)(int,unsigned int,int,int)) { if (id <= 0 || id >= timer_data_num) { printf("delete_timer error : no such timer %d\n", id); return -1; } if (timer_data[id].func != func) { printf("delete_timer error : function dismatch %08x(%s) != %08x(%s)\n", - (int)timer_data[id].func, - search_timer_func_list(timer_data[id].func), - (int)func, - search_timer_func_list(func)); + (int)timer_data[id].func, search_timer_func_list(timer_data[id].func), + (int)func, search_timer_func_list(func)); return -2; } // そのうち消えるにまかせる timer_data[id].func = NULL; timer_data[id].type = TIMER_ONCE_AUTODEL; - timer_data[id].tick -= 60 * 60 * 1000; +// timer_data[id].tick -= 60 * 60 * 1000; + return 0; } -int addtick_timer(int tid,unsigned int tick) -{ +int addtick_timer(int tid,unsigned int tick) { return timer_data[tid].tick += tick; } -struct TimerData* get_timer(int tid) -{ + +struct TimerData* get_timer(int tid) { return &timer_data[tid]; } +int do_timer(unsigned int tick) { + int i, nextmin = 1000; -int do_timer(unsigned int tick) -{ - int i,nextmin = 1000; - -#if 0 - static int disp_tick = 0; - if (DIFF_TICK(disp_tick,tick)<-5000 || DIFF_TICK(disp_tick,tick)>5000) { - printf("timer %d(%d + %d)\n",timer_data_num,timer_heap[0],free_timer_list_pos); - disp_tick = tick; - } -#endif - - while((i = top_timer_heap()) >= 0) { - if (DIFF_TICK(timer_data[i].tick , tick)>0) { - nextmin = DIFF_TICK(timer_data[i].tick , tick); + while(timer_heap_num) { + i = timer_heap[timer_heap_num - 1]; // next shorter element + if (DIFF_TICK(timer_data[i].tick, tick) > 0) { + nextmin = DIFF_TICK(timer_data[i].tick, tick); break; } - pop_timer_heap(); + if (timer_heap_num > 0) // suppress the actual element from the table + timer_heap_num--; timer_data[i].type |= TIMER_REMOVE_HEAP; if (timer_data[i].func) { - if (DIFF_TICK(timer_data[i].tick , tick) < -1000) { + if (DIFF_TICK(timer_data[i].tick, tick) < -1000) { // 1秒以上の大幅な遅延が発生しているので、 // timer処理タイミングを現在値とする事で // 呼び出し時タイミング(引数のtick)相対で処理してる // timer関数の次回処理タイミングを遅らせる - timer_data[i].func(i,tick,timer_data[i].id,timer_data[i].data); + timer_data[i].func(i, tick, timer_data[i].id, timer_data[i].data); } else { - timer_data[i].func(i,timer_data[i].tick,timer_data[i].id,timer_data[i].data); + timer_data[i].func(i, timer_data[i].tick, timer_data[i].id, timer_data[i].data); } } - if (timer_data[i].type&TIMER_REMOVE_HEAP) { + if (timer_data[i].type & TIMER_REMOVE_HEAP) { switch(timer_data[i].type & ~TIMER_REMOVE_HEAP) { case TIMER_ONCE_AUTODEL: timer_data[i].type = 0; if (free_timer_list_pos >= free_timer_list_max) { free_timer_list_max += 256; - RECREATE(free_timer_list, int, free_timer_list_max); - memset(free_timer_list + (free_timer_list_max - 256), 0, - 256 * sizeof(free_timer_list[0])); + //REALLOC(free_timer_list, int, free_timer_list_max); + free_timer_list = (int *) aRealloc(free_timer_list, sizeof(int) * free_timer_list_max); + memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); } free_timer_list[free_timer_list_pos++] = i; break; @@ -307,13 +285,31 @@ int do_timer(unsigned int tick) } } - if(nextmin < TIMER_MIN_INTERVEL) + if (nextmin < 10) + nextmin = 10; - nextmin = TIMER_MIN_INTERVEL; return nextmin; } -void timer_final() -{ - free(timer_data); +void timer_final() { + struct timer_func_list* tfl = tfl_root, *tfl2; + +// while (tfl) { +// tfl2 = tfl; +// aFree(tfl->name); +// aFree(tfl); +// tfl = tfl2->next; // access on already freed memory +// } + + while (tfl) { + tfl2 = tfl->next; // copy next pointer + aFree(tfl->name); // free structures + aFree(tfl); + tfl = tfl2; // use copied pointer for next cycle + } + + if (timer_data) aFree(timer_data); + if (timer_heap) aFree(timer_heap); + if (free_timer_list) aFree(free_timer_list); } + diff --git a/src/common/timer.h b/src/common/timer.h index f6fc5c84d..81086cb70 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -3,6 +3,12 @@ #ifndef _TIMER_H_ #define _TIMER_H_ +#ifdef __WIN32 +/* We need winsock lib to have timeval struct - windows is weirdo */ +#define __USE_W32_SOCKETS +#include <windows.h> +#endif + #define BASE_TICK 5 #define TIMER_ONCE_AUTODEL 1 @@ -25,6 +31,10 @@ struct TimerData { // Function prototype declaration +#ifdef __WIN32 +void gettimeofday(struct timeval *t, void *dummy); +#endif + unsigned int gettick_nocache(void); unsigned int gettick(void); @@ -40,6 +50,6 @@ int do_timer(unsigned int tick); int add_timer_func_list(int (*)(int,unsigned int,int,int),char*); char* search_timer_func_list(int (*)(int,unsigned int,int,int)); -extern void timer_final(); +void timer_final(); #endif // _TIMER_H_ diff --git a/src/common/utils.c b/src/common/utils.c index 2a09f773e..732b1d366 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1,8 +1,10 @@ #include <string.h> #include "utils.h" #include <stdio.h> -#include <stdlib.h> #include <stdarg.h> +#include <stdlib.h> +#include "malloc.h" +#include "mmo.h" void dump(unsigned char *buffer, int num) { @@ -111,7 +113,7 @@ void str_lower(char *name) // Allocate a StringBuf [MouseJstr] struct StringBuf * StringBuf_Malloc() { - struct StringBuf * ret = (struct StringBuf *) malloc(sizeof(struct StringBuf)); + struct StringBuf * ret = (struct StringBuf *) aMallocA(sizeof(struct StringBuf)); StringBuf_Init(ret); return ret; } @@ -119,7 +121,7 @@ struct StringBuf * StringBuf_Malloc() // Initialize a previously allocated StringBuf [MouseJstr] void StringBuf_Init(struct StringBuf * sbuf) { sbuf->max_ = 1024; - sbuf->ptr_ = sbuf->buf_ = (char *) malloc(sbuf->max_ + 1); + sbuf->ptr_ = sbuf->buf_ = (char *) aMallocA(sbuf->max_ + 1); } // printf into a StringBuf, moving the pointer [MouseJstr] @@ -142,7 +144,7 @@ int StringBuf_Printf(struct StringBuf *sbuf,const char *fmt,...) /* Else try again with more space. */ sbuf->max_ *= 2; // twice the old size off = sbuf->ptr_ - sbuf->buf_; - sbuf->buf_ = (char *) realloc(sbuf->buf_, sbuf->max_ + 1); + sbuf->buf_ = (char *) aRealloc(sbuf->buf_, sbuf->max_ + 1); sbuf->ptr_ = sbuf->buf_ + off; } } @@ -156,7 +158,7 @@ int StringBuf_Append(struct StringBuf *buf1,const struct StringBuf *buf2) if (size2 >= buf1_avail) { int off = buf1->ptr_ - buf1->buf_; buf1->max_ += size2; - buf1->buf_ = (char *) realloc(buf1->buf_, buf1->max_ + 1); + buf1->buf_ = (char *) aRealloc(buf1->buf_, buf1->max_ + 1); buf1->ptr_ = buf1->buf_ + off; } @@ -168,7 +170,7 @@ int StringBuf_Append(struct StringBuf *buf1,const struct StringBuf *buf2) // Destroy a StringBuf [MouseJstr] void StringBuf_Destroy(struct StringBuf *sbuf) { - free(sbuf->buf_); + aFree(sbuf->buf_); sbuf->ptr_ = sbuf->buf_ = 0; } @@ -176,7 +178,7 @@ void StringBuf_Destroy(struct StringBuf *sbuf) void StringBuf_Free(struct StringBuf *sbuf) { StringBuf_Destroy(sbuf); - free(sbuf); + aFree(sbuf); } // Return the built string from the StringBuf [MouseJstr] diff --git a/src/common/utils.h b/src/common/utils.h index 248bcd867..63c3f21ec 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -1,5 +1,6 @@ -#ifndef UTILS_H -#define UTILS_H +#ifndef COMMON_UTILS_H +#define COMMON_UTILS_H + #ifndef NULL #define NULL (void *)0 @@ -20,16 +21,23 @@ #endif -void dump(unsigned char *buffer, int num); + void dump(unsigned char *buffer, int num); + #define CREATE(result, type, number) do {\ if ((number) * sizeof(type) <= 0) \ printf("SYSERR: Zero bytes or less requested at %s:%d.\n", __FILE__, __LINE__); \ - if (!((result) = (type *) calloc ((number), sizeof(type)))) \ + if (!((result) = (type *) aCalloc ((number), sizeof(type)))) \ + { perror("SYSERR: malloc failure"); abort(); } } while(0) + +#define CREATE_A(result, type, number) do {\ + if ((number) * sizeof(type) <= 0) \ + printf("SYSERR: Zero bytes or less requested at %s:%d.\n", __FILE__, __LINE__); \ + if (!((result) = (type *) aCallocA ((number), sizeof(type)))) \ { perror("SYSERR: malloc failure"); abort(); } } while(0) #define RECREATE(result,type,number) do {\ - if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\ + if (!((result) = (type *) aRealloc ((result), sizeof(type) * (number))))\ { printf("SYSERR: realloc failure"); abort(); } } while(0) struct StringBuf { |