summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/HPM.c10
-rw-r--r--src/common/console.c12
-rw-r--r--src/common/core.c10
-rw-r--r--src/common/db.c1
-rw-r--r--src/common/ers.c21
-rw-r--r--src/common/ers.h6
-rw-r--r--src/common/malloc.c146
-rw-r--r--src/common/malloc.h16
-rw-r--r--src/common/mmo.h16
-rw-r--r--src/common/mutex.c2
-rw-r--r--src/common/random.c2
-rw-r--r--src/common/socket.c72
-rw-r--r--src/common/socket.h14
-rw-r--r--src/common/sql.c149
-rw-r--r--src/common/sql.h192
-rw-r--r--src/common/strlib.h10
-rw-r--r--src/common/timer.c37
-rw-r--r--src/common/timer.h41
18 files changed, 467 insertions, 290 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 28ea8f413..9283360dc 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -265,7 +265,7 @@ void hplugins_share_defaults(void) {
HPM->share((void*)get_svn_revision,"get_svn_revision");
HPM->share((void*)get_git_hash,"get_git_hash");
HPM->share(DB, "DB");
- HPM->share(malloclib, "malloclib");
+ HPM->share(iMalloc, "iMalloc");
/* socket */
HPM->share(RFIFOSKIP,"RFIFOSKIP");
HPM->share(WFIFOSET,"WFIFOSET");
@@ -281,12 +281,8 @@ void hplugins_share_defaults(void) {
/* sql */
HPM->share(SQL,"SQL");
/* timer */
- HPM->share(gettick,"gettick");
- HPM->share(add_timer,"add_timer");
- HPM->share(add_timer_interval,"add_timer_interval");
- HPM->share(add_timer_func_list,"add_timer_func_list");
- HPM->share(delete_timer,"delete_timer");
- HPM->share(get_uptime,"get_uptime");
+ HPM->share(iTimer,"iTimer");
+
}
CPCMD(plugins) {
if( HPM->plugin_count == 0 ) {
diff --git a/src/common/console.c b/src/common/console.c
index ba93b8e09..08daec04e 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -85,6 +85,9 @@ CPCMD(exit) {
CPCMD(ers_report) {
ers_report();
}
+CPCMD(mem_report) {
+ memmgr_report(line?atoi(line):0);
+}
CPCMD(help) {
unsigned int i = 0;
for ( i = 0; i < console->cmd_list_count; i++ ) {
@@ -98,7 +101,7 @@ CPCMD(help) {
}
/* [Ind/Hercules] */
CPCMD(malloc_usage) {
- unsigned int val = (unsigned int)malloclib->usage();
+ unsigned int val = (unsigned int)iMalloc->usage();
ShowInfo("malloc_usage: %.2f MB\n",(double)(val)/1024);
}
#define CP_DEF_C(x) { #x , NULL , NULL, NULL }
@@ -115,6 +118,7 @@ void console_load_defaults(void) {
CP_DEF(help),
CP_DEF_C(server),
CP_DEF_S(ers_report,server),
+ CP_DEF_S(mem_report,server),
CP_DEF_S(malloc_usage,server),
CP_DEF_S(exit,server),
};
@@ -227,8 +231,10 @@ void console_parse_sub(char *line) {
char *tok;
char sublist[CP_CMD_LENGTH * 5];
unsigned int i, len = 0;
+
memcpy(bline, line, 200);
tok = strtok(line, " ");
+
for ( i = 0; i < console->cmd_list_count; i++ ) {
if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
break;
@@ -363,8 +369,8 @@ void console_parse_init(void) {
exit(EXIT_FAILURE);
}
- add_timer_func_list(console->parse_timer, "console_parse_timer");
- add_timer_interval(gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */
+ iTimer->add_timer_func_list(console->parse_timer, "console_parse_timer");
+ iTimer->add_timer_interval(iTimer->gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */
}
#endif /* CONSOLE_INPUT */
diff --git a/src/common/core.c b/src/common/core.c
index 0959e6fc9..c53d2243b 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -307,7 +307,7 @@ int main (int argc, char **argv) {
}
core_defaults();
- malloclib->init();// needed for Show* in display_title() [FlavioJS]
+ iMalloc->init();// needed for Show* in display_title() [FlavioJS]
console->display_title();
@@ -329,7 +329,7 @@ int main (int argc, char **argv) {
cevents_init();
#endif
- timer_init();
+ iTimer->init();
console->init();
@@ -343,7 +343,7 @@ int main (int argc, char **argv) {
{// Main runtime cycle
int next;
while (runflag != CORE_ST_STOP) {
- next = do_timer(gettick_nocache());
+ next = iTimer->do_timer(iTimer->gettick_nocache());
do_sockets(next);
}
}
@@ -354,14 +354,14 @@ int main (int argc, char **argv) {
#ifndef MINICORE
HPM->final();
#endif
- timer_final();
+ iTimer->final();
socket_final();
DB->final();
mempool_final();
rathread_final();
#endif
- malloclib->final();
+ iMalloc->final();
return 0;
}
diff --git a/src/common/db.c b/src/common/db.c
index 561371787..99c758a8d 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -2611,6 +2611,7 @@ void* db_data2ptr(DBData *data)
void db_init(void) {
db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE);
db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE);
+ ers_chunk_size(db_alloc_ers, 50);
DB_COUNTSTAT(db_init);
}
diff --git a/src/common/ers.c b/src/common/ers.c
index 69b7609d6..22269a51f 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -84,6 +84,9 @@ typedef struct ers_cache
// Objects in-use count
unsigned int UsedObjs;
+ // Default = ERS_BLOCK_ENTRIES, can be adjusted for performance for individual cache sizes.
+ unsigned int ChunkSize;
+
// Linked list
struct ers_cache *Next, *Prev;
} ers_cache_t;
@@ -136,6 +139,7 @@ static ers_cache_t *ers_find_cache(unsigned int size)
cache->Used = 0;
cache->UsedObjs = 0;
cache->Max = 0;
+ cache->ChunkSize = ERS_BLOCK_ENTRIES;
if (CacheList == NULL)
{
@@ -200,10 +204,10 @@ static void *ers_obj_alloc_entry(ERS self)
RECREATE(instance->Cache->Blocks, unsigned char *, instance->Cache->Max);
}
- CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * ERS_BLOCK_ENTRIES);
+ CREATE(instance->Cache->Blocks[instance->Cache->Used], unsigned char, instance->Cache->ObjectSize * instance->Cache->ChunkSize);
instance->Cache->Used++;
- instance->Cache->Free = ERS_BLOCK_ENTRIES -1;
+ instance->Cache->Free = instance->Cache->ChunkSize -1;
ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)];
}
@@ -286,6 +290,18 @@ static void ers_obj_destroy(ERS self)
aFree(instance);
}
+void ers_cache_size(ERS self, unsigned int new_size) {
+ struct ers_instance_t *instance = (struct ers_instance_t *)self;
+
+ if (instance == NULL) {//change as per piotrhalaczkiewicz comment
+ ShowError("ers_cache_size: NULL object, skipping...\n");
+ return;
+ }
+
+ instance->Cache->ChunkSize = new_size;
+}
+
+
ERS ers_new(uint32 size, char *name, enum ERSOptions options)
{
struct ers_instance_t *instance;
@@ -299,6 +315,7 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options)
instance->VTable.free = ers_obj_free_entry;
instance->VTable.entry_size = ers_obj_entry_size;
instance->VTable.destroy = ers_obj_destroy;
+ instance->VTable.chunk_size = ers_cache_size;
instance->Name = ( options & ERS_OPT_FREE_NAME ) ? aStrdup(name) : name;
instance->Options = options;
diff --git a/src/common/ers.h b/src/common/ers.h
index 4871d8d50..51701d778 100644
--- a/src/common/ers.h
+++ b/src/common/ers.h
@@ -119,6 +119,8 @@ typedef struct eri {
*/
void (*destroy)(struct eri *self);
+ /* */
+ void (*chunk_size) (struct eri *self, unsigned int new_size);
} *ERS;
#ifdef DISABLE_ERS
@@ -127,6 +129,7 @@ typedef struct eri {
# define ers_free(obj,entry) aFree(entry)
# define ers_entry_size(obj) (size_t)0
# define ers_destroy(obj)
+# define ers_chunk_size(obj,size)
// Disable the public functions
# define ers_new(size,name,options) NULL
# define ers_report()
@@ -138,6 +141,7 @@ typedef struct eri {
# define ers_free(obj,entry) (obj)->free((obj),(entry))
# define ers_entry_size(obj) (obj)->entry_size(obj)
# define ers_destroy(obj) (obj)->destroy(obj)
+# define ers_chunk_size(obj,size) (obj)->chunk_size(obj,size)
/**
* Get a new instance of the manager that handles the specified entry size.
@@ -154,7 +158,7 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options);
/**
* Print a report about the current state of the Entry Reusage System.
* Shows information about the global system and each entry manager.
- * The number of entries are checked and a warning is shown if extra reusable
+ * The number of entries are checked and a warning is shown if extra reusable
* entries are found.
* The extra entries are included in the count of reusable entries.
*/
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 592027f56..d629aa63f 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -200,6 +200,8 @@ static struct unit_head_large *unit_head_large_first = NULL;
static struct block* block_malloc(unsigned short hash);
static void block_free(struct block* p);
static size_t memmgr_usage_bytes;
+static size_t memmgr_usage_bytes_t;
+
#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ]))
#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0)
@@ -245,6 +247,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
/* At that time, the distinction by assigning NULL to unit_head.block */
if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
+ memmgr_usage_bytes_t += size+sizeof(struct unit_head_large);
if(p != NULL) {
p->size = size;
p->unit_head.block = NULL;
@@ -332,7 +335,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func )
{
- void *p = malloclib->malloc(num * size,file,line,func);
+ void *p = iMalloc->malloc(num * size,file,line,func);
memset(p,0,num * size);
return p;
}
@@ -341,7 +344,7 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
{
size_t old_size;
if(memblock == NULL) {
- return malloclib->malloc(size,file,line,func);
+ return iMalloc->malloc(size,file,line,func);
}
old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
@@ -353,11 +356,11 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
return memblock;
} else {
// Size Large
- void *p = malloclib->malloc(size,file,line,func);
+ void *p = iMalloc->malloc(size,file,line,func);
if(p != NULL) {
memcpy(p,memblock,old_size);
}
- malloclib->free(memblock,file,line,func);
+ iMalloc->free(memblock,file,line,func);
return p;
}
}
@@ -368,7 +371,7 @@ char* _mstrdup(const char *p, const char *file, int line, const char *func )
return NULL;
} else {
size_t len = strlen(p);
- char *string = (char *)malloclib->malloc(len + 1,file,line,func);
+ char *string = (char *)iMalloc->malloc(len + 1,file,line,func);
memcpy(string,p,len+1);
return string;
}
@@ -401,6 +404,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
head_large->next->prev = head_large->prev;
}
memmgr_usage_bytes -= head_large->size;
+ memmgr_usage_bytes_t -= head_large->size + sizeof(struct unit_head_large);
#ifdef DEBUG_MEMMGR
// set freed memory to 0xfd
memset(ptr, 0xfd, head_large->size);
@@ -457,6 +461,7 @@ static struct block* block_malloc(unsigned short hash)
} else {
/* Newly allocated space for the block */
p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
+ memmgr_usage_bytes_t += sizeof(struct block) * (BLOCK_ALLOC);
if(p == NULL) {
ShowFatalError("Memory manager::block_alloc failed.\n");
exit(EXIT_FAILURE);
@@ -621,7 +626,7 @@ static void memmgr_final (void)
memmgr_log (buf);
#endif /* LOG_MEMMGR */
// get block pointer and free it [celest]
- malloclib->free(ptr, ALC_MARK);
+ iMalloc->free(ptr, ALC_MARK);
}
}
}
@@ -650,6 +655,86 @@ static void memmgr_final (void)
}
#endif /* LOG_MEMMGR */
}
+/* [Ind/Hercules] */
+void memmgr_report (int extra) {
+ struct block *block = block_first;
+ struct unit_head_large *large = unit_head_large_first;
+ unsigned int count = 0, size = 0;
+ int j;
+ unsigned short msize = 1024;
+ struct {
+ const char *file;
+ unsigned short line;
+ unsigned int size;
+ unsigned int count;
+ } data[100];
+ memset(&data, 0, sizeof(data));
+
+ if( extra != 0 )
+ msize = extra;
+
+ while (block) {
+ if (block->unit_used) {
+ int i;
+ for (i = 0; i < block->unit_maxused; i++) {
+ struct unit_head *head = block2unit(block, i);
+ if( head->block != NULL && head->size > msize ) {
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].file == head->file && data[j].line == head->line ) {
+ data[j].size += head->size;
+ data[j].count += 1;
+ break;
+ } else if( data[j].size == 0 ) {
+ data[j].file = head->file;
+ data[j].line = head->line;
+ data[j].size = head->size;
+ data[j].count += 1;
+ break;
+ }
+ }
+ size += (unsigned int)head->size;
+ count++;
+ }
+ }
+ }
+ block = block->block_next;
+ }
+
+ while(large) {
+ if( large->size > msize ) {
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].file == large->unit_head.file && data[j].line == large->unit_head.line ) {
+ data[j].size += large->size;
+ data[j].count += 1;
+ break;
+ } else if( data[j].size == 0 ) {
+ data[j].file = large->unit_head.file;
+ data[j].line = large->unit_head.line;
+ data[j].size = large->size;
+ data[j].count += 1;
+ break;
+ }
+ }
+ size += (unsigned int)large->size;
+ count++;
+ }
+ large = large->next;
+ }
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].size != 0 ) {
+ ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024);
+ }
+ }
+ ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024);
+ ShowMessage("[malloc] : internal usage %.2f MB | %.2f MB\n",(double)((memmgr_usage_bytes_t-memmgr_usage_bytes)/1024)/1024,(double)((memmgr_usage_bytes_t)/1024)/1024);
+
+ if( extra ) {
+ ShowMessage("[malloc] : unit_head_large: %d bytes\n",sizeof(struct unit_head_large));
+ ShowMessage("[malloc] : unit_head: %d bytes\n",sizeof(struct unit_head));
+ ShowMessage("[malloc] : block: %d bytes\n",sizeof(struct block));
+ }
+
+}
static void memmgr_init (void)
{
@@ -677,8 +762,7 @@ void malloc_memory_check(void)
/// Returns true if a pointer is valid.
/// The check is best-effort, false positives are possible.
-bool malloc_verify_ptr(void* ptr)
-{
+bool malloc_verify_ptr(void* ptr) {
#ifdef USE_MEMMGR
return memmgr_verify(ptr) && MEMORY_VERIFY(ptr);
#else
@@ -687,8 +771,7 @@ bool malloc_verify_ptr(void* ptr)
}
-size_t malloc_usage (void)
-{
+size_t malloc_usage (void) {
#ifdef USE_MEMMGR
return memmgr_usage ();
#else
@@ -696,16 +779,16 @@ size_t malloc_usage (void)
#endif
}
-void malloc_final (void)
-{
+void malloc_final (void) {
#ifdef USE_MEMMGR
memmgr_final ();
#endif
MEMORY_CHECK();
}
-void malloc_init (void)
-{
+void malloc_init (void) {
+ memmgr_usage_bytes_t = 0;
+ memmgr_usage_bytes = 0;
#if defined(DMALLOC) && defined(CYGWIN)
// http://dmalloc.com/docs/latest/online/dmalloc_19.html
dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
@@ -720,27 +803,26 @@ void malloc_init (void)
#endif
}
-void malloc_defaults()
-{
- malloclib = &malloclib_s;
- malloclib->init = malloc_init;
- malloclib->final = malloc_final;
- malloclib->memory_check = malloc_memory_check;
- malloclib->usage = malloc_usage;
- malloclib->verify_ptr = malloc_verify_ptr;
+void malloc_defaults(void) {
+ iMalloc = &iMalloc_s;
+ iMalloc->init = malloc_init;
+ iMalloc->final = malloc_final;
+ iMalloc->memory_check = malloc_memory_check;
+ iMalloc->usage = malloc_usage;
+ iMalloc->verify_ptr = malloc_verify_ptr;
// Athena's built-in Memory Manager
#ifdef USE_MEMMGR
- malloclib->malloc = _mmalloc;
- malloclib->calloc = _mcalloc;
- malloclib->realloc = _mrealloc;
- malloclib->astrdup = _mstrdup;
- malloclib->free = _mfree;
+ iMalloc->malloc = _mmalloc;
+ iMalloc->calloc = _mcalloc;
+ iMalloc->realloc = _mrealloc;
+ iMalloc->astrdup = _mstrdup;
+ iMalloc->free = _mfree;
#else
- malloclib->malloc = aMalloc_;
- malloclib->calloc = aCalloc_;
- malloclib->realloc = aRealloc_;
- malloclib->astrdup = aStrdup_;
- malloclib->free = aFree_;
+ iMalloc->malloc = aMalloc_;
+ iMalloc->calloc = aCalloc_;
+ iMalloc->realloc = aRealloc_;
+ iMalloc->astrdup = aStrdup_;
+ iMalloc->free = aFree_;
#endif
}
diff --git a/src/common/malloc.h b/src/common/malloc.h
index 34a26b56e..834781905 100644
--- a/src/common/malloc.h
+++ b/src/common/malloc.h
@@ -30,11 +30,11 @@
#undef LOG_MEMMGR
#endif
-# define aMalloc(n) malloclib->malloc (n,ALC_MARK)
-# define aCalloc(m,n) malloclib->calloc (m,n,ALC_MARK)
-# define aRealloc(p,n) malloclib->realloc (p,n,ALC_MARK)
-# define aStrdup(p) malloclib->astrdup (p,ALC_MARK)
-# define aFree(p) malloclib->free (p,ALC_MARK)
+# define aMalloc(n) iMalloc->malloc (n,ALC_MARK)
+# define aCalloc(m,n) iMalloc->calloc (m,n,ALC_MARK)
+# define aRealloc(p,n) iMalloc->realloc (p,n,ALC_MARK)
+# define aStrdup(p) iMalloc->astrdup (p,ALC_MARK)
+# define aFree(p) iMalloc->free (p,ALC_MARK)
/////////////// Buffer Creation /////////////////
// Full credit for this goes to Shinomori [Ajarn]
@@ -78,7 +78,9 @@ struct malloc_interface {
size_t (*usage) (void);
void (*init) (void);
void (*final) (void);
-} malloclib_s;
+} iMalloc_s;
-struct malloc_interface *malloclib;
+void memmgr_report (int extra);
+
+struct malloc_interface *iMalloc;
#endif /* _MALLOC_H_ */
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 172b27b15..6e5dae099 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -54,6 +54,13 @@
// Comment the following line if your client is NOT ragexeRE (required because of conflicting packets in ragexe vs ragexeRE).
#define PACKETVER_RE
+// Client support for experimental RagexeRE UI present in 2012-04-10 and 2012-04-18
+#ifdef PACKETVER_RE
+#if (PACKETVER == 20120410) || (PACKETVER == 20120418)
+ #define PARTY_RECRUIT
+#endif
+#endif
+
// Comment the following line to disable sc_data saving. [Skotlex]
#define ENABLE_SC_SAVING
@@ -72,7 +79,6 @@
#define MAX_HOTKEYS 38
#endif
-#define MAX_MAP_PER_SERVER 1500 // Increased to allow creation of Instance Maps
#define MAX_INVENTORY 100
//Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well.
#define MAX_CHARS 9
@@ -84,7 +90,7 @@
#define MAX_ZENY 1000000000
#define MAX_FAME 1000000000
#define MAX_CART 100
-#define MAX_SKILL 1477
+#define MAX_SKILL 1478
#define MAX_SKILL_ID 10015 // [Ind/Hercules] max used skill ID
#define GLOBAL_REG_NUM 256 // Max permanent character variables per char
#define ACCOUNT_REG_NUM 64 // Max permanent local account variables per account
@@ -104,7 +110,7 @@
#define MAX_GUILDSKILL 15 // Increased max guild skills because of new skills [Sara-chan]
#define MAX_GUILDLEVEL 50
#define MAX_GUARDIANS 8 // Local max per castle. [Skotlex]
-#define MAX_QUEST_DB 2400 // Max quests that the server will load
+#define MAX_QUEST_DB 2410 // Max quests that the server will load
#define MAX_QUEST_OBJECTIVES 3 // Max quest objectives for a quest
#define MAX_START_ITEMS 32 // Max number of items allowed to be given to a char whenever it's created. [mkbu95]
@@ -527,6 +533,10 @@ struct guild {
/* TODO: still used for something?|: */
unsigned short save_flag; // for TXT saving
+
+ short *instance;
+ unsigned short instances;
+
void *channel;
};
diff --git a/src/common/mutex.c b/src/common/mutex.c
index 6b4f55119..6bb1efdab 100644
--- a/src/common/mutex.c
+++ b/src/common/mutex.c
@@ -201,7 +201,7 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks){
pthread_cond_wait( &c->hCond, &m->hMutex );
}else{
struct timespec wtime;
- int64 exact_timeout = gettick() + timeout_ticks;
+ int64 exact_timeout = iTimer->gettick() + timeout_ticks;
wtime.tv_sec = exact_timeout/1000;
wtime.tv_nsec = (exact_timeout%1000)*1000000;
diff --git a/src/common/random.c b/src/common/random.c
index 5c048c7eb..a7d432e34 100644
--- a/src/common/random.c
+++ b/src/common/random.c
@@ -17,7 +17,7 @@
/// Initializes the random number generator with an appropriate seed.
void rnd_init(void)
{
- uint32 seed = gettick();
+ uint32 seed = iTimer->gettick();
seed += (uint32)time(NULL);
#if defined(WIN32)
seed += GetCurrentProcessId();
diff --git a/src/common/socket.c b/src/common/socket.c
index 5126d231b..15b20b16f 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -280,9 +280,10 @@ void set_nonblocking(int fd, unsigned long yes)
ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg());
}
-void setsocketopts(int fd)
-{
+void setsocketopts(int fd, struct hSockOpt *opt) {
int yes = 1; // reuse fix
+ struct linger lopt;
+
#if !defined(WIN32)
// set SO_REAUSEADDR to true, unix only. on windows this option causes
// the previous owner of the socket to give up, which is not desirable
@@ -297,15 +298,22 @@ void setsocketopts(int fd)
// The RO protocol is mainly single-packet request/response, plus the FIFO model already does packet grouping anyway.
sSetsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes));
+ if( opt && opt->setTimeo ) {
+ struct timeval timeout;
+
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+
+ sSetsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
+ sSetsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
+ }
+
// force the socket into no-wait, graceful-close mode (should be the default, but better make sure)
//(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/closesocket_2.asp)
- {
- struct linger opt;
- opt.l_onoff = 0; // SO_DONTLINGER
- opt.l_linger = 0; // Do not care
- if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&opt, sizeof(opt)) )
+ lopt.l_onoff = 0; // SO_DONTLINGER
+ lopt.l_linger = 0; // Do not care
+ if( sSetsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&lopt, sizeof(lopt)) )
ShowWarning("setsocketopts: Unable to set SO_LINGER mode for connection #%d!\n", fd);
- }
}
/*======================================
@@ -404,8 +412,7 @@ void flush_fifos(void)
/*======================================
* CORE : Connection functions
*--------------------------------------*/
-int connect_client(int listen_fd)
-{
+int connect_client(int listen_fd) {
int fd;
struct sockaddr_in client_address;
socklen_t len;
@@ -417,20 +424,18 @@ int connect_client(int listen_fd)
ShowError("connect_client: accept failed (%s)!\n", error_msg());
return -1;
}
- if( fd == 0 )
- {// reserved
+ if( fd == 0 ) { // reserved
ShowError("connect_client: Socket #0 is reserved - Please report this!!!\n");
sClose(fd);
return -1;
}
- if( fd >= FD_SETSIZE )
- {// socket number too big
+ if( fd >= FD_SETSIZE ) { // socket number too big
ShowError("connect_client: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
sClose(fd);
return -1;
}
- setsocketopts(fd);
+ setsocketopts(fd,NULL);
set_nonblocking(fd, 1);
#ifndef MINICORE
@@ -457,25 +462,22 @@ int make_listen_bind(uint32 ip, uint16 port)
fd = sSocket(AF_INET, SOCK_STREAM, 0);
- if( fd == -1 )
- {
+ if( fd == -1 ) {
ShowError("make_listen_bind: socket creation failed (%s)!\n", error_msg());
exit(EXIT_FAILURE);
}
- if( fd == 0 )
- {// reserved
+ if( fd == 0 ) { // reserved
ShowError("make_listen_bind: Socket #0 is reserved - Please report this!!!\n");
sClose(fd);
return -1;
}
- if( fd >= FD_SETSIZE )
- {// socket number too big
+ if( fd >= FD_SETSIZE ) { // socket number too big
ShowError("make_listen_bind: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
sClose(fd);
return -1;
}
- setsocketopts(fd);
+ setsocketopts(fd,NULL);
set_nonblocking(fd, 1);
server_address.sin_family = AF_INET;
@@ -503,7 +505,7 @@ int make_listen_bind(uint32 ip, uint16 port)
return fd;
}
-int make_connection(uint32 ip, uint16 port, bool silent) {
+int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt) {
struct sockaddr_in remote_address;
int fd;
int result;
@@ -514,31 +516,29 @@ int make_connection(uint32 ip, uint16 port, bool silent) {
ShowError("make_connection: socket creation failed (%s)!\n", error_msg());
return -1;
}
- if( fd == 0 )
- {// reserved
+ if( fd == 0 ) {// reserved
ShowError("make_connection: Socket #0 is reserved - Please report this!!!\n");
sClose(fd);
return -1;
}
- if( fd >= FD_SETSIZE )
- {// socket number too big
+ if( fd >= FD_SETSIZE ) {// socket number too big
ShowError("make_connection: New socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (currently %d) for your OS to fix this!\n", fd, FD_SETSIZE);
sClose(fd);
return -1;
}
- setsocketopts(fd);
+ setsocketopts(fd,opt);
remote_address.sin_family = AF_INET;
remote_address.sin_addr.s_addr = htonl(ip);
remote_address.sin_port = htons(port);
- if( !silent )
+ if( !( opt && opt->silent ) )
ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
result = sConnect(fd, (struct sockaddr *)(&remote_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) {
- if( !silent )
+ if( !( opt && opt->silent ) )
ShowError("make_connection: connect failed (socket #%d, %s)!\n", fd, error_msg());
do_close(fd);
return -1;
@@ -947,9 +947,9 @@ static int connect_check_(uint32 ip)
if( hist->ddos )
{// flagged as DDoS
return (connect_ok == 2 ? 1 : 0);
- } else if( DIFF_TICK(gettick(),hist->tick) < ddos_interval )
+ } else if( DIFF_TICK(iTimer->gettick(),hist->tick) < ddos_interval )
{// connection within ddos_interval
- hist->tick = gettick();
+ hist->tick = iTimer->gettick();
if( hist->count++ >= ddos_count )
{// DDoS attack detected
hist->ddos = 1;
@@ -959,7 +959,7 @@ static int connect_check_(uint32 ip)
return connect_ok;
} else
{// not within ddos_interval, clear data
- hist->tick = gettick();
+ hist->tick = iTimer->gettick();
hist->count = 0;
return connect_ok;
}
@@ -970,7 +970,7 @@ static int connect_check_(uint32 ip)
CREATE(hist, ConnectHistory, 1);
memset(hist, 0, sizeof(ConnectHistory));
hist->ip = ip;
- hist->tick = gettick();
+ hist->tick = iTimer->gettick();
hist->next = connect_history[ip&0xFFFF];
connect_history[ip&0xFFFF] = hist;
return connect_ok;
@@ -1331,8 +1331,8 @@ void socket_init(void)
#ifndef MINICORE
// Delete old connection history every 5 minutes
memset(connect_history, 0, sizeof(connect_history));
- add_timer_func_list(connect_check_clear, "connect_check_clear");
- add_timer_interval(gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
+ iTimer->add_timer_func_list(connect_check_clear, "connect_check_clear");
+ iTimer->add_timer_interval(iTimer->gettick()+1000, connect_check_clear, 0, 0, 5*60*1000);
#endif
ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur);
diff --git a/src/common/socket.h b/src/common/socket.h
index 4879cb109..b58cbdccf 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _SOCKET_H_
#define _SOCKET_H_
@@ -48,6 +49,9 @@
} \
} while(0)
+/* [Ind/Hercules] */
+#define RFIFO2PTR(fd,len) (void*)(session[fd]->rdata + len)
+
// buffer I/O macros
#define RBUFP(p,pos) (((uint8*)(p)) + (pos))
#define RBUFB(p,pos) (*(uint8*)RBUFP((p),(pos)))
@@ -94,6 +98,10 @@ struct socket_data
void* session_data; // stores application-specific data related to the session
};
+struct hSockOpt {
+ unsigned int silent : 1;
+ unsigned int setTimeo : 1;
+};
// Data prototype declaration
@@ -113,7 +121,7 @@ extern bool session_isActive(int fd);
// Function prototype declaration
int make_listen_bind(uint32 ip, uint16 port);
-int make_connection(uint32 ip, uint16 port, bool silent);
+int make_connection(uint32 ip, uint16 port, struct hSockOpt *opt);
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size);
int realloc_writefifo(int fd, size_t addition);
int WFIFOSET(int fd, size_t len);
diff --git a/src/common/sql.c b/src/common/sql.c
index 391211183..441b860da 100644
--- a/src/common/sql.c
+++ b/src/common/sql.c
@@ -116,9 +116,9 @@ int Sql_GetTimeout(Sql* self, uint32* out_timeout)
size_t len;
if( SQL_SUCCESS == SQL->NextRow(self) &&
SQL_SUCCESS == SQL->GetData(self, 1, &data, &len) ) {
- *out_timeout = (uint32)strtoul(data, NULL, 10);
- SQL->FreeResult(self);
- return SQL_SUCCESS;
+ *out_timeout = (uint32)strtoul(data, NULL, 10);
+ SQL->FreeResult(self);
+ return SQL_SUCCESS;
}
SQL->FreeResult(self);
}
@@ -210,7 +210,7 @@ static int Sql_P_Keepalive(Sql* self)
// establish keepalive
ping_interval = timeout - 30; // 30-second reserve
//add_timer_func_list(Sql_P_KeepaliveTimer, "Sql_P_KeepaliveTimer");
- return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr_t)self, ping_interval*1000);
+ return iTimer->add_timer_interval(iTimer->gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr_t)self, ping_interval*1000);
}
@@ -404,7 +404,7 @@ void Sql_Free(Sql* self)
{
SQL->FreeResult(self);
StrBuf->Destroy(&self->buf);
- if( self->keepalive != INVALID_TIMER ) delete_timer(self->keepalive, Sql_P_KeepaliveTimer);
+ if( self->keepalive != INVALID_TIMER ) iTimer->delete_timer(self->keepalive, Sql_P_KeepaliveTimer);
aFree(self);
}
}
@@ -447,7 +447,7 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type,
case SQLDT_NULL: bind->buffer_type = MYSQL_TYPE_NULL;
buffer_len = 0;// FIXME length = ? [FlavioJS]
break;
- // fixed size
+ // fixed size
case SQLDT_UINT8: bind->is_unsigned = 1;
case SQLDT_INT8: bind->buffer_type = MYSQL_TYPE_TINY;
buffer_len = 1;
@@ -464,7 +464,7 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type,
case SQLDT_INT64: bind->buffer_type = MYSQL_TYPE_LONGLONG;
buffer_len = 8;
break;
- // platform dependent size
+ // platform dependent size
case SQLDT_UCHAR: bind->is_unsigned = 1;
case SQLDT_CHAR: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char));
buffer_len = sizeof(char);
@@ -485,14 +485,14 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type,
case SQLDT_LONGLONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int64));
buffer_len = sizeof(int64);
break;
- // floating point
+ // floating point
case SQLDT_FLOAT: bind->buffer_type = MYSQL_TYPE_FLOAT;
buffer_len = 4;
break;
case SQLDT_DOUBLE: bind->buffer_type = MYSQL_TYPE_DOUBLE;
buffer_len = 8;
break;
- // other
+ // other
case SQLDT_STRING:
case SQLDT_ENUM: bind->buffer_type = MYSQL_TYPE_STRING;
break;
@@ -524,25 +524,25 @@ static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_ty
ShowDebug("%stype=%s%u, length=%d\n", prefix, sign, type, length);
return;
#define SHOW_DEBUG_OF(x) case x: type_string = #x; break
- SHOW_DEBUG_OF(MYSQL_TYPE_TINY);
- SHOW_DEBUG_OF(MYSQL_TYPE_SHORT);
- SHOW_DEBUG_OF(MYSQL_TYPE_LONG);
- SHOW_DEBUG_OF(MYSQL_TYPE_INT24);
- SHOW_DEBUG_OF(MYSQL_TYPE_LONGLONG);
- SHOW_DEBUG_OF(MYSQL_TYPE_DECIMAL);
- SHOW_DEBUG_OF(MYSQL_TYPE_FLOAT);
- SHOW_DEBUG_OF(MYSQL_TYPE_DOUBLE);
- SHOW_DEBUG_OF(MYSQL_TYPE_TIMESTAMP);
- SHOW_DEBUG_OF(MYSQL_TYPE_DATE);
- SHOW_DEBUG_OF(MYSQL_TYPE_TIME);
- SHOW_DEBUG_OF(MYSQL_TYPE_DATETIME);
- SHOW_DEBUG_OF(MYSQL_TYPE_YEAR);
- SHOW_DEBUG_OF(MYSQL_TYPE_STRING);
- SHOW_DEBUG_OF(MYSQL_TYPE_VAR_STRING);
- SHOW_DEBUG_OF(MYSQL_TYPE_BLOB);
- SHOW_DEBUG_OF(MYSQL_TYPE_SET);
- SHOW_DEBUG_OF(MYSQL_TYPE_ENUM);
- SHOW_DEBUG_OF(MYSQL_TYPE_NULL);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TINY);
+ SHOW_DEBUG_OF(MYSQL_TYPE_SHORT);
+ SHOW_DEBUG_OF(MYSQL_TYPE_LONG);
+ SHOW_DEBUG_OF(MYSQL_TYPE_INT24);
+ SHOW_DEBUG_OF(MYSQL_TYPE_LONGLONG);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DECIMAL);
+ SHOW_DEBUG_OF(MYSQL_TYPE_FLOAT);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DOUBLE);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TIMESTAMP);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DATE);
+ SHOW_DEBUG_OF(MYSQL_TYPE_TIME);
+ SHOW_DEBUG_OF(MYSQL_TYPE_DATETIME);
+ SHOW_DEBUG_OF(MYSQL_TYPE_YEAR);
+ SHOW_DEBUG_OF(MYSQL_TYPE_STRING);
+ SHOW_DEBUG_OF(MYSQL_TYPE_VAR_STRING);
+ SHOW_DEBUG_OF(MYSQL_TYPE_BLOB);
+ SHOW_DEBUG_OF(MYSQL_TYPE_SET);
+ SHOW_DEBUG_OF(MYSQL_TYPE_ENUM);
+ SHOW_DEBUG_OF(MYSQL_TYPE_NULL);
#undef SHOW_DEBUG_TYPE_OF
}
ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix);
@@ -610,7 +610,7 @@ int SqlStmt_Prepare(SqlStmt* self, const char* query, ...)
va_list args;
va_start(args, query);
- res = SqlStmt_PrepareV(self, query, args);
+ res = SQL->StmtPrepareV(self, query, args);
va_end(args);
return res;
@@ -624,7 +624,7 @@ int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args)
if( self == NULL )
return SQL_ERROR;
- SqlStmt_FreeResult(self);
+ SQL->StmtFreeResult(self);
StrBuf->Clear(&self->buf);
StrBuf->Vprintf(&self->buf, query, args);
if( mysql_stmt_prepare(self->stmt, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) )
@@ -646,7 +646,7 @@ int SqlStmt_PrepareStr(SqlStmt* self, const char* query)
if( self == NULL )
return SQL_ERROR;
- SqlStmt_FreeResult(self);
+ SQL->StmtFreeResult(self);
StrBuf->Clear(&self->buf);
StrBuf->AppendStr(&self->buf, query);
if( mysql_stmt_prepare(self->stmt, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) )
@@ -677,14 +677,14 @@ size_t SqlStmt_NumParams(SqlStmt* self)
int SqlStmt_BindParam(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, void* buffer, size_t buffer_len)
{
if( self == NULL )
- return SQL_ERROR;
+ return SQL_ERROR;
if( !self->bind_params )
{// initialize the bindings
size_t i;
size_t count;
- count = SqlStmt_NumParams(self);
+ count = SQL->StmtNumParams(self);
if( self->max_params < count )
{
self->max_params = count;
@@ -709,7 +709,7 @@ int SqlStmt_Execute(SqlStmt* self)
if( self == NULL )
return SQL_ERROR;
- SqlStmt_FreeResult(self);
+ SQL->StmtFreeResult(self);
if( (self->bind_params && mysql_stmt_bind_param(self->stmt, self->params)) ||
mysql_stmt_execute(self->stmt) )
{
@@ -772,7 +772,7 @@ int SqlStmt_BindColumn(SqlStmt* self, size_t idx, enum SqlDataType buffer_type,
size_t i;
size_t cols;
- cols = SqlStmt_NumColumns(self);
+ cols = SQL->StmtNumColumns(self);
if( self->max_columns < cols )
{
self->max_columns = cols;
@@ -843,7 +843,7 @@ int SqlStmt_NextRow(SqlStmt* self)
}
// find truncated column
- cols = SqlStmt_NumColumns(self);
+ cols = SQL->StmtNumColumns(self);
for( i = 0; i < cols; ++i )
{
column = &self->columns[i];
@@ -868,7 +868,7 @@ int SqlStmt_NextRow(SqlStmt* self)
}
// propagate column lengths and clear unused parts of string/enum/blob buffers
- cols = SqlStmt_NumColumns(self);
+ cols = SQL->StmtNumColumns(self);
for( i = 0; i < cols; ++i )
{
length = self->column_lengths[i].length;
@@ -946,21 +946,21 @@ void SqlStmt_Free(SqlStmt* self)
void hercules_mysql_error_handler(unsigned int ecode) {
static unsigned int retry = 1;
switch( ecode ) {
- case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */
- if( mysql_reconnect_type == 1 ) {
- if( ++retry > mysql_reconnect_count ) {
- ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry);
- exit(EXIT_FAILURE);
- }
+ case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */
+ if( mysql_reconnect_type == 1 ) {
+ if( ++retry > mysql_reconnect_count ) {
+ ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry);
+ exit(EXIT_FAILURE);
}
- break;
+ }
+ break;
}
}
void Sql_inter_server_read(const char* cfgName, bool first) {
int i;
char line[1024], w1[1024], w2[1024];
FILE* fp;
-
+
fp = fopen(cfgName, "r");
if(fp == NULL) {
if( first ) {
@@ -970,22 +970,22 @@ void Sql_inter_server_read(const char* cfgName, bool first) {
ShowError("File not found: %s\n", cfgName);
return;
}
-
+
while(fgets(line, sizeof(line), fp)) {
i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2);
if(i != 2)
continue;
-
+
if(!strcmpi(w1,"mysql_reconnect_type")) {
mysql_reconnect_type = atoi(w2);
switch( mysql_reconnect_type ) {
- case 1:
- case 2:
- break;
- default:
- ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type);
- mysql_reconnect_type = 1;
- break;
+ case 1:
+ case 2:
+ break;
+ default:
+ ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type);
+ mysql_reconnect_type = 1;
+ break;
}
} else if(!strcmpi(w1,"mysql_reconnect_count")) {
mysql_reconnect_count = atoi(w2);
@@ -995,7 +995,7 @@ void Sql_inter_server_read(const char* cfgName, bool first) {
Sql_inter_server_read(w2,false);
}
fclose(fp);
-
+
return;
}
@@ -1003,7 +1003,7 @@ void Sql_HerculesUpdateCheck(Sql* self) {
char line[22];// "yyyy-mm-dd--hh-mm" (17) + ".sql" (4) + 1
FILE* ifp;/* index fp */
unsigned int performed = 0;
-
+
if( !( ifp = fopen("sql-files/upgrades/index.txt", "r") ) ) {
ShowError("SQL upgrade index was not found!\n");
return;
@@ -1013,22 +1013,22 @@ void Sql_HerculesUpdateCheck(Sql* self) {
char path[41];// "sql-files/upgrades/" (19) + "yyyy-mm-dd--hh-mm" (17) + ".sql" (4) + 1
char timestamp[11];// "1360186680" (10) + 1
FILE* ufp;/* upgrade fp */
-
+
if( line[0] == '\n' || ( line[0] == '/' && line[1] == '/' ) )/* skip \n and "//" comments */
continue;
-
+
sprintf(path,"sql-files/upgrades/%s",line);
-
+
if( !( ufp = fopen(path, "r") ) ) {
ShowError("SQL upgrade file %s was not found!\n",path);
continue;
}
-
+
if( fgetc(ufp) != '#' )
continue;
-
+
fseek (ufp,1,SEEK_SET);/* woo. skip the # */
-
+
if( fgets(timestamp,sizeof(timestamp),ufp) ) {
unsigned int timestampui = atol(timestamp);
if( SQL_ERROR == SQL->Query(self, "SELECT 1 FROM `sql_updates` WHERE `timestamp` = '%u' LIMIT 1", timestampui) )
@@ -1038,12 +1038,12 @@ void Sql_HerculesUpdateCheck(Sql* self) {
performed++;
}
}
-
+
fclose(ufp);
}
-
+
fclose(ifp);
-
+
if( performed ) {
ShowSQL("If you did apply these updates or would like to be skip, insert a new entry in your sql_updates table with the timestamp of each file\n");
}
@@ -1054,7 +1054,7 @@ void Sql_Init(void) {
}
void sql_defaults(void) {
SQL = &sql_s;
-
+
SQL->Connect = Sql_Connect;
SQL->GetTimeout = Sql_GetTimeout;
SQL->GetColumnNames = Sql_GetColumnNames;
@@ -1074,4 +1074,21 @@ void sql_defaults(void) {
SQL->ShowDebug_ = Sql_ShowDebug_;
SQL->Free = Sql_Free;
SQL->Malloc = Sql_Malloc;
+
+ /* SqlStmt defaults [Susu] */
+ SQL->StmtBindColumn = SqlStmt_BindColumn;
+ SQL->StmtBindParam = SqlStmt_BindParam;
+ SQL->StmtExecute = SqlStmt_Execute;
+ SQL->StmtFree = SqlStmt_Free;
+ SQL->StmtFreeResult = SqlStmt_FreeResult;
+ SQL->StmtLastInsertId = SqlStmt_LastInsertId;
+ SQL->StmtMalloc = SqlStmt_Malloc;
+ SQL->StmtNextRow = SqlStmt_NextRow;
+ SQL->StmtNumColumns = SqlStmt_NumColumns;
+ SQL->StmtNumParams = SqlStmt_NumParams;
+ SQL->StmtNumRows = SqlStmt_NumRows;
+ SQL->StmtPrepare = SqlStmt_Prepare;
+ SQL->StmtPrepareStr = SqlStmt_PrepareStr;
+ SQL->StmtPrepareV = SqlStmt_PrepareV;
+ SQL->StmtShowDebug_ = SqlStmt_ShowDebug_;
}
diff --git a/src/common/sql.h b/src/common/sql.h
index d5a0eda2c..535990649 100644
--- a/src/common/sql.h
+++ b/src/common/sql.h
@@ -142,145 +142,157 @@ struct sql_interface {
void (*Free) (Sql* self);
/// Allocates and initializes a new Sql handle.
struct Sql *(*Malloc) (void);
-} sql_s;
-struct sql_interface *SQL;
-void sql_defaults(void);
-#if defined(SQL_REMOVE_SHOWDEBUG)
- #define Sql_ShowDebug(self) (void)0
-#else
- #define Sql_ShowDebug(self) SQL->ShowDebug_(self, __FILE__, __LINE__)
-#endif
+ ///////////////////////////////////////////////////////////////////////////////
+ // Prepared Statements
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parameters are placed in the statement by embedding question mark ('?')
+ // characters into the query at the appropriate positions.
+ // The markers are legal only in places where they represent data.
+ // The markers cannot be inside quotes. Quotes will be added automatically
+ // when they are required.
+ //
+ // example queries with parameters:
+ // 1) SELECT col FROM table WHERE id=?
+ // 2) INSERT INTO table(col1,col2) VALUES(?,?)
-///////////////////////////////////////////////////////////////////////////////
-// Prepared Statements
-///////////////////////////////////////////////////////////////////////////////
-// Parameters are placed in the statement by embedding question mark ('?')
-// characters into the query at the appropriate positions.
-// The markers are legal only in places where they represent data.
-// The markers cannot be inside quotes. Quotes will be added automatically
-// when they are required.
-//
-// example queries with parameters:
-// 1) SELECT col FROM table WHERE id=?
-// 2) INSERT INTO table(col1,col2) VALUES(?,?)
-/// Allocates and initializes a new SqlStmt handle.
-/// It uses the connection of the parent Sql handle.
-/// Queries in Sql and SqlStmt are independent and don't affect each other.
-///
-/// @return SqlStmt handle or NULL if an error occured
-struct SqlStmt* SqlStmt_Malloc(Sql* sql);
+ /*=====================================
+ SQL Statement interface [Susu]
+ *-------------------------------------*/
+ /// Allocates and initializes a new SqlStmt handle.
+ /// It uses the connection of the parent Sql handle.
+ /// Queries in Sql and SqlStmt are independent and don't affect each other.
+ ///
+ /// @return SqlStmt handle or NULL if an error occured
+ struct SqlStmt* (*StmtMalloc)(Sql* sql);
-/// Prepares the statement.
-/// Any previous result is freed and all parameter bindings are removed.
-/// The query is constructed as if it was sprintf.
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_Prepare(SqlStmt* self, const char* query, ...);
-/// Prepares the statement.
-/// Any previous result is freed and all parameter bindings are removed.
-/// The query is constructed as if it was svprintf.
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args);
+ /// Prepares the statement.
+ /// Any previous result is freed and all parameter bindings are removed.
+ /// The query is constructed as if it was sprintf.
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtPrepare)(SqlStmt* self, const char* query, ...);
+ /// Prepares the statement.
+ /// Any previous result is freed and all parameter bindings are removed.
+ /// The query is constructed as if it was svprintf.
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtPrepareV)(SqlStmt* self, const char* query, va_list args);
-/// Prepares the statement.
-/// Any previous result is freed and all parameter bindings are removed.
-/// The query is used directly.
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_PrepareStr(SqlStmt* self, const char* query);
+ /// Prepares the statement.
+ /// Any previous result is freed and all parameter bindings are removed.
+ /// The query is used directly.
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtPrepareStr)(SqlStmt* self, const char* query);
-/// Returns the number of parameters in the prepared statement.
-///
-/// @return Number or paramenters
-size_t SqlStmt_NumParams(SqlStmt* self);
+ /// Returns the number of parameters in the prepared statement.
+ ///
+ /// @return Number or paramenters
+ size_t (*StmtNumParams)(SqlStmt* self);
-/// Binds a parameter to a buffer.
-/// The buffer data will be used when the statement is executed.
-/// All parameters should have bindings.
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_BindParam(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len);
+ /// Binds a parameter to a buffer.
+ /// The buffer data will be used when the statement is executed.
+ /// All parameters should have bindings.
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtBindParam)(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len);
-/// Executes the prepared statement.
-/// Any previous result is freed and all column bindings are removed.
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_Execute(SqlStmt* self);
+ /// Executes the prepared statement.
+ /// Any previous result is freed and all column bindings are removed.
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtExecute)(SqlStmt* self);
-/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement.
-///
-/// @return Value of the auto-increment column
-uint64 SqlStmt_LastInsertId(SqlStmt* self);
+ /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement.
+ ///
+ /// @return Value of the auto-increment column
+ uint64 (*StmtLastInsertId)(SqlStmt* self);
-/// Returns the number of columns in each row of the result.
-///
-/// @return Number of columns
-size_t SqlStmt_NumColumns(SqlStmt* self);
+ /// Returns the number of columns in each row of the result.
+ ///
+ /// @return Number of columns
+ size_t (*StmtNumColumns)(SqlStmt* self);
+
+
+
+ /// Binds the result of a column to a buffer.
+ /// The buffer will be filled with data when the next row is fetched.
+ /// For string/enum buffer types there has to be enough space for the data
+ /// and the nul-terminator (an extra byte).
+ ///
+ /// @return SQL_SUCCESS or SQL_ERROR
+ int (*StmtBindColumn)(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null);
+
+
+
+ /// Returns the number of rows in the result.
+ ///
+ /// @return Number of rows
+ uint64 (*StmtNumRows)(SqlStmt* self);
-/// Binds the result of a column to a buffer.
-/// The buffer will be filled with data when the next row is fetched.
-/// For string/enum buffer types there has to be enough space for the data
-/// and the nul-terminator (an extra byte).
-///
-/// @return SQL_SUCCESS or SQL_ERROR
-int SqlStmt_BindColumn(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null);
+ /// Fetches the next row.
+ /// All column bindings will be filled with data.
+ ///
+ /// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
+ int (*StmtNextRow)(SqlStmt* self);
-/// Returns the number of rows in the result.
-///
-/// @return Number of rows
-uint64 SqlStmt_NumRows(SqlStmt* self);
+ /// Frees the result of the statement execution.
+ void (*StmtFreeResult)(SqlStmt* self);
+ /// Frees a SqlStmt returned by SqlStmt_Malloc.
+ void (*StmtFree)(SqlStmt* self);
-/// Fetches the next row.
-/// All column bindings will be filled with data.
-///
-/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA
-int SqlStmt_NextRow(SqlStmt* self);
+ void (*StmtShowDebug_)(SqlStmt* self, const char* debug_file, const unsigned long debug_line);
+} sql_s;
+
+struct sql_interface *SQL;
+void sql_defaults(void);
-/// Frees the result of the statement execution.
-void SqlStmt_FreeResult(SqlStmt* self);
+#if defined(SQL_REMOVE_SHOWDEBUG)
+#define Sql_ShowDebug(self) (void)0
+#else
+#define Sql_ShowDebug(self) SQL->ShowDebug_(self, __FILE__, __LINE__)
+#endif
void Sql_HerculesUpdateCheck(Sql* self);
#if defined(SQL_REMOVE_SHOWDEBUG)
- #define SqlStmt_ShowDebug(self) (void)0
+#define SqlStmt_ShowDebug(self) (void)0
#else
- #define SqlStmt_ShowDebug(self) SqlStmt_ShowDebug_(self, __FILE__, __LINE__)
+#define SqlStmt_ShowDebug(self) SQL->StmtShowDebug_(self, __FILE__, __LINE__)
#endif
/// Shows debug information (with statement).
-void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line);
-/// Frees a SqlStmt returned by SqlStmt_Malloc.
-void SqlStmt_Free(SqlStmt* self);
+
+
void Sql_Init(void);
diff --git a/src/common/strlib.h b/src/common/strlib.h
index 4a073c3bc..9b1875d45 100644
--- a/src/common/strlib.h
+++ b/src/common/strlib.h
@@ -8,9 +8,13 @@
#include "../common/cbasetypes.h"
#include <stdarg.h>
-#define __USE_GNU // required to enable strnlen on some platforms
-#include <string.h>
-#undef __USE_GNU
+#ifndef __USE_GNU
+ #define __USE_GNU // required to enable strnlen on some platforms
+ #include <string.h>
+ #undef __USE_GNU
+#else
+ #include <string.h>
+#endif
#ifdef WIN32
#define HAVE_STRTOK_R
diff --git a/src/common/timer.c b/src/common/timer.c
index edb46bd71..955a971c8 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -257,7 +257,7 @@ int timer_add_interval(unsigned int tick, TimerFunc func, int id, intptr_t data,
int tid;
if( interval < 1 ) {
- ShowError("timer_add_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick()));
+ ShowError("timer_add_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, iTimer->gettick()));
return INVALID_TIMER;
}
@@ -300,7 +300,7 @@ int timer_do_delete(int tid, TimerFunc func) {
/// Adjusts a timer's expiration time.
/// Returns the new tick value, or -1 if it fails.
int timer_addtick(int tid, unsigned int tick) {
- return settick_timer(tid, timer_data[tid].tick+tick);
+ return iTimer->settick_timer(tid, timer_data[tid].tick+tick);
}
/// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one).
@@ -409,15 +409,26 @@ void timer_final(void) {
BHEAP_CLEAR(timer_heap);
if (free_timer_list) aFree(free_timer_list);
}
-void timer_defaults(void) {
- gettick = timer_gettick;
- gettick_nocache = timer_gettick_nocache;
- add_timer = timer_add;
- add_timer_interval = timer_add_interval;
- add_timer_func_list = timer_add_func_list;
- get_timer = timer_get;
- delete_timer = timer_do_delete;
- addtick_timer = timer_addtick;
- settick_timer = timer_settick;
- get_uptime = timer_get_uptime;
+/*=====================================
+* Default Functions : timer.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void timer_defaults(void) {
+ iTimer = &iTimer_s;
+
+ /* funcs */
+ iTimer->gettick = timer_gettick;
+ iTimer->gettick_nocache = timer_gettick_nocache;
+ iTimer->add_timer = timer_add;
+ iTimer->add_timer_interval = timer_add_interval;
+ iTimer->add_timer_func_list = timer_add_func_list;
+ iTimer->get_timer = timer_get;
+ iTimer->delete_timer = timer_do_delete;
+ iTimer->addtick_timer = timer_addtick;
+ iTimer->settick_timer = timer_settick;
+ iTimer->get_uptime = timer_get_uptime;
+ iTimer->do_timer = do_timer;
+ iTimer->init = timer_init;
+ iTimer->final = timer_final;
}
diff --git a/src/common/timer.h b/src/common/timer.h
index 902679f51..50f1c354b 100644
--- a/src/common/timer.h
+++ b/src/common/timer.h
@@ -1,10 +1,8 @@
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-
#ifndef _TIMER_H_
#define _TIMER_H_
-
#include "../common/cbasetypes.h"
#define DIFF_TICK(a,b) ((int)((a)-(b)))
@@ -34,27 +32,36 @@ struct TimerData {
intptr_t data;
};
-// Function prototype declaration
-int do_timer(unsigned int tick);
-void timer_init(void);
-void timer_final(void);
+/*=====================================
+* Interface : timer.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct timer_interface {
+
+ /* funcs */
+ unsigned int (*gettick) (void);
+ unsigned int (*gettick_nocache) (void);
+
+ int (*add_timer) (unsigned int tick, TimerFunc func, int id, intptr_t data);
+ int (*add_timer_interval) (unsigned int tick, TimerFunc func, int id, intptr_t data, int interval);
+ const struct TimerData *(*get_timer) (int tid);
+ int (*delete_timer) (int tid, TimerFunc func);
-/* Hercules Renewal Phase One */
-unsigned int (*gettick) (void);
-unsigned int (*gettick_nocache) (void);
+ int (*addtick_timer) (int tid, unsigned int tick);
+ int (*settick_timer) (int tid, unsigned int tick);
-int (*add_timer) (unsigned int tick, TimerFunc func, int id, intptr_t data);
-int (*add_timer_interval) (unsigned int tick, TimerFunc func, int id, intptr_t data, int interval);
-const struct TimerData *(*get_timer) (int tid);
-int (*delete_timer) (int tid, TimerFunc func);
+ int (*add_timer_func_list) (TimerFunc func, char* name);
-int (*addtick_timer) (int tid, unsigned int tick);
-int (*settick_timer) (int tid, unsigned int tick);
+ unsigned long (*get_uptime) (void);
-int (*add_timer_func_list) (TimerFunc func, char* name);
+ int (*do_timer) (unsigned int tick);
+ void (*init) (void);
+ void (*final) (void);
+} iTimer_s;
-unsigned long (*get_uptime) (void);
+struct timer_interface *iTimer;
void timer_defaults(void);