summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authoramber <amber@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-04-07 18:00:13 +0000
committeramber <amber@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-04-07 18:00:13 +0000
commit1a348ede4934a1ba78f337ee1dffe11a699f4bef (patch)
tree883d4c1ae282fb67e1720f81c20f564499298ff4 /src/common
parent7cb0d361f1b4260b47ab1da99224332947320553 (diff)
parenta6cd6538e4271ea08dc86803e8b7e8c8f235960b (diff)
downloadhercules-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/GNUmakefile14
-rw-r--r--src/common/Makefile33
-rw-r--r--src/common/buffer.h18
-rw-r--r--src/common/core.c250
-rw-r--r--src/common/core.h11
-rw-r--r--src/common/db.c203
-rw-r--r--src/common/db.h25
-rw-r--r--src/common/dll.h25
-rw-r--r--src/common/grfio.c251
-rw-r--r--src/common/grfio.h3
-rw-r--r--src/common/lock.c44
-rw-r--r--src/common/malloc.c510
-rw-r--r--src/common/malloc.h66
-rw-r--r--src/common/mmo.h78
-rw-r--r--src/common/nullpo.h11
-rw-r--r--src/common/showmsg.c125
-rw-r--r--src/common/showmsg.h93
-rw-r--r--src/common/socket.c672
-rw-r--r--src/common/socket.h32
-rw-r--r--src/common/strlib.c98
-rw-r--r--src/common/strlib.h13
-rw-r--r--src/common/timer.c290
-rw-r--r--src/common/timer.h12
-rw-r--r--src/common/utils.c16
-rw-r--r--src/common/utils.h18
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 {