Trimmed trailing whitespaces in /src/common
This commit is contained in:
parent
366aeeaafe
commit
cc9d08538a
@ -4,16 +4,16 @@
|
||||
#ifndef _rA_ATOMIC_H_
|
||||
#define _rA_ATOMIC_H_
|
||||
|
||||
// Atomic Operations
|
||||
// Atomic Operations
|
||||
// (Interlocked CompareExchange, Add .. and so on ..)
|
||||
//
|
||||
//
|
||||
// Implementation varies / depends on:
|
||||
// - Architecture
|
||||
// - Compiler
|
||||
// - Operating System
|
||||
//
|
||||
// our Abstraction is fully API-Compatible to Microsofts implementation @ NT5.0+
|
||||
//
|
||||
//
|
||||
#include "cbasetypes.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
@ -29,14 +29,14 @@ forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch,
|
||||
_asm{
|
||||
lea esi,_cmp;
|
||||
lea edi,exch;
|
||||
|
||||
|
||||
mov eax,[esi];
|
||||
mov edx,4[esi];
|
||||
mov ebx,[edi];
|
||||
mov ecx,4[edi];
|
||||
mov esi,dest;
|
||||
|
||||
lock CMPXCHG8B [esi];
|
||||
|
||||
lock CMPXCHG8B [esi];
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,11 +88,11 @@ forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 v
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
// The __sync functions are available on x86 or ARMv6+
|
||||
//need to proper dig into arm macro,
|
||||
//need to proper dig into arm macro,
|
||||
//see http://sourceforge.net/p/predef/wiki/Architectures/
|
||||
#if !defined(__x86_64__) && !defined(__i386__) \
|
||||
&& ( !defined(__ARM_ARCH_VERSION__) || __ARM_ARCH_VERSION__ < 6 ) \
|
||||
&& ( !defined(__ARM_ARCH) && __ARM_ARCH < 6 )
|
||||
&& ( !defined(__ARM_ARCH) && __ARM_ARCH < 6 )
|
||||
#error Your Target Platfrom is not supported
|
||||
#endif
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *
|
||||
config_setting_set_format(set, src->format);
|
||||
} else if (CONFIG_TYPE_INT64 == config_setting_type(src)) {
|
||||
set = config_setting_set_int64_elem(parent, -1, config_setting_get_int64(src));
|
||||
config_setting_set_format(set, src->format);
|
||||
config_setting_set_format(set, src->format);
|
||||
} else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) {
|
||||
config_setting_set_float_elem(parent, -1, config_setting_get_float(src));
|
||||
} else if (CONFIG_TYPE_STRING == config_setting_type(src)) {
|
||||
@ -83,10 +83,10 @@ void config_setting_copy_aggregate(config_setting_t *parent, const config_settin
|
||||
return;
|
||||
|
||||
n = config_setting_length(src);
|
||||
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (config_setting_is_group(src)) {
|
||||
config_setting_copy_simple(newAgg, config_setting_get_elem(src, i));
|
||||
config_setting_copy_simple(newAgg, config_setting_get_elem(src, i));
|
||||
} else {
|
||||
config_setting_copy_elem(newAgg, config_setting_get_elem(src, i));
|
||||
}
|
||||
|
||||
@ -363,7 +363,7 @@ int main (int argc, char **argv)
|
||||
do_init(argc,argv);
|
||||
|
||||
// Main runtime cycle
|
||||
while (runflag != CORE_ST_STOP) {
|
||||
while (runflag != CORE_ST_STOP) {
|
||||
int next = do_timer(gettick_nocache());
|
||||
do_sockets(next);
|
||||
}
|
||||
|
||||
@ -1339,7 +1339,7 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...);
|
||||
|
||||
|
||||
/// Resets the length and clears content, so the vector is empty
|
||||
///
|
||||
///
|
||||
/// @param __vec Vector
|
||||
#define VECTOR_RESET(__vec) \
|
||||
if( VECTOR_LENGTH(__vec) > 0 ) { \
|
||||
|
||||
@ -16,7 +16,7 @@ struct EVDP_DATA{
|
||||
|
||||
|
||||
enum EVDP_EVENTFLAGS{
|
||||
EVDP_EVENT_IN = 1, // Incomming data
|
||||
EVDP_EVENT_IN = 1, // Incomming data
|
||||
EVDP_EVENT_OUT = 2, // Connection accepts writing.
|
||||
EVDP_EVENT_HUP = 4 // Connection Closed.
|
||||
};
|
||||
@ -28,7 +28,7 @@ typedef struct EVDP_EVENT{
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Network Event Dispatcher Initialization / Finalization routines
|
||||
*/
|
||||
void evdp_init();
|
||||
@ -40,22 +40,22 @@ void evdp_final();
|
||||
*
|
||||
* @param *out_ev pointer to array in size at least of max_events.
|
||||
* @param max_events max no of events to report with this call (coalesc)
|
||||
* @param timeout_ticks max time to wait in ticks (milliseconds)
|
||||
* @param timeout_ticks max time to wait in ticks (milliseconds)
|
||||
*
|
||||
* @Note:
|
||||
* The function will block until an event has occured on one of the monitored connections
|
||||
* or the timeout of timeout_ticks has passed by.
|
||||
* Upon successfull call (changed connections) this function will write the connection
|
||||
* Identifier & event to the out_fds array.
|
||||
* Identifier & event to the out_fds array.
|
||||
*
|
||||
* @return 0 -> Timeout, > 0 no of changed connections.
|
||||
*/
|
||||
int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Applys the given mask on the given connection.
|
||||
*
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *ep event data pointer for the connection
|
||||
* @param mask new event mask we're monitoring for.
|
||||
@ -63,20 +63,20 @@ int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks);
|
||||
//void evdp_apply(int32 fd, EVDP_DATA *ep, int32 mask);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Adds a connection (listner) to the event notification system.
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *ep event data pointer for the connection
|
||||
* @param *ep event data pointer for the connection
|
||||
*
|
||||
* @note:
|
||||
* @note:
|
||||
* Listener type sockets are edge triggered, (see epoll manual for more information)
|
||||
* - This basicaly means that youll receive one event, adn you have to accept until accept returns an error (nothing to accept)
|
||||
*
|
||||
* MONITORS by default: IN
|
||||
*
|
||||
*
|
||||
* @return success indicator.
|
||||
*/
|
||||
*/
|
||||
bool evdp_addlistener(int32 fd, EVDP_DATA *ep);
|
||||
|
||||
/**
|
||||
@ -84,9 +84,9 @@ bool evdp_addlistener(int32 fd, EVDP_DATA *ep);
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *ep event data pointr for the connection
|
||||
*
|
||||
*
|
||||
* @note:
|
||||
*
|
||||
*
|
||||
* MONITORS by default: IN, HUP
|
||||
*
|
||||
* @return success indicator.
|
||||
@ -102,11 +102,11 @@ bool evdp_addclient(int32 fd, EVDP_DATA *ep);
|
||||
* @note:
|
||||
* Outgoing connection type sockets are getting monitored for connection established
|
||||
* successfull
|
||||
* - if the connection has been established - we're generitng a writable notification .. (send)
|
||||
* - if the connection has been established - we're generitng a writable notification .. (send)
|
||||
* this is typical for BSD / posix conform network stacks.
|
||||
* - Additinionally its edge triggered.
|
||||
*
|
||||
* @see evdp_outgoingconnection_established
|
||||
* @see evdp_outgoingconnection_established
|
||||
*
|
||||
*
|
||||
* @return success indicator
|
||||
@ -114,14 +114,14 @@ bool evdp_addclient(int32 fd, EVDP_DATA *ep);
|
||||
bool evdp_addconnecting(int32 fd, EVDP_DATA *ep);
|
||||
|
||||
/**
|
||||
* Adds an outgoing connection to the normal event notification system after it has been successfully established.
|
||||
* Adds an outgoing connection to the normal event notification system after it has been successfully established.
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *ep event data pointer for the conneciton.
|
||||
|
||||
* @note
|
||||
|
||||
* @note
|
||||
* after this call, its handled like a normal "client" connection (incomming)
|
||||
*
|
||||
*
|
||||
* @rturn success indicator
|
||||
*/
|
||||
bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep);
|
||||
@ -134,19 +134,19 @@ bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep);
|
||||
*
|
||||
* @note:
|
||||
* the connection must be already added (as client or listener)
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return success indicator
|
||||
*/
|
||||
bool evdp_writable_add(int32 fd, EVDP_DATA *ep);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Removes the connection from writable notification monitoring
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *ep event data pointr for the connection
|
||||
*
|
||||
*/
|
||||
*/
|
||||
void evdp_writable_remove(int32 fd, EVDP_DATA *ep);
|
||||
|
||||
/**
|
||||
@ -157,7 +157,7 @@ void evdp_writable_remove(int32 fd, EVDP_DATA *ep);
|
||||
*
|
||||
*
|
||||
* @note:
|
||||
* this will also clear the given EVENT_DATA block
|
||||
* this will also clear the given EVENT_DATA block
|
||||
* so the connection slot is in an "initial" blank status / ready to get reused.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Event Dispatcher Abstraction for EPOLL
|
||||
// Event Dispatcher Abstraction for EPOLL
|
||||
//
|
||||
// Author: Florian Wilkemeyer <fw@f-ws.de>
|
||||
//
|
||||
@ -9,30 +9,30 @@
|
||||
//
|
||||
|
||||
|
||||
#define EPOLL_MAX_PER_CYCLE 10 // Max Events to coalesc. per cycle.
|
||||
#define EPOLL_MAX_PER_CYCLE 10 // Max Events to coalesc. per cycle.
|
||||
|
||||
|
||||
static int epoll_fd = -1;
|
||||
|
||||
|
||||
void evdp_init(){
|
||||
|
||||
|
||||
epoll_fd = epoll_create( EPOLL_MAX_PER_CYCLE );
|
||||
if(epoll_fd == -1){
|
||||
ShowFatalError("evdp [EPOLL]: Cannot create event dispatcher (errno: %u / %s)\n", errno, strerror(errno) );
|
||||
ShowFatalError("evdp [EPOLL]: Cannot create event dispatcher (errno: %u / %s)\n", errno, strerror(errno) );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
}//end: evdp_init()
|
||||
|
||||
|
||||
void evdp_final(){
|
||||
|
||||
|
||||
if(epoll_fd != -1){
|
||||
close(epoll_fd);
|
||||
epoll_fd = -1;
|
||||
}
|
||||
|
||||
|
||||
}//end: evdp_final()
|
||||
|
||||
|
||||
@ -40,64 +40,64 @@ int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks){
|
||||
struct epoll_event l_events[EPOLL_MAX_PER_CYCLE];
|
||||
register struct epoll_event *ev;
|
||||
register int nfds, n;
|
||||
|
||||
|
||||
if(max_events > EPOLL_MAX_PER_CYCLE)
|
||||
max_events = EPOLL_MAX_PER_CYCLE;
|
||||
|
||||
|
||||
nfds = epoll_wait( epoll_fd, l_events, max_events, timeout_ticks);
|
||||
if(nfds == -1){
|
||||
// @TODO: check if core is in shutdown mode. if - ignroe error.
|
||||
|
||||
|
||||
ShowFatalError("evdp [EPOLL]: epoll_wait returned bad / unexpected status (errno: %u / %s)\n", errno, strerror(errno));
|
||||
exit(1); //..
|
||||
}
|
||||
|
||||
|
||||
// Loop thru all events and copy it to the local ra evdp_event.. struct.
|
||||
for(n = 0; n < nfds; n++){
|
||||
ev = &l_events[n];
|
||||
|
||||
|
||||
out_fds->fd = ev->data.fd;
|
||||
out_fds->events = 0; // clear
|
||||
|
||||
|
||||
if(ev->events & EPOLLHUP)
|
||||
out_fds->events |= EVDP_EVENT_HUP;
|
||||
|
||||
|
||||
if(ev->events & EPOLLIN)
|
||||
out_fds->events |= EVDP_EVENT_IN;
|
||||
|
||||
|
||||
if(ev->events & EPOLLOUT)
|
||||
out_fds->events |= EVDP_EVENT_OUT;
|
||||
|
||||
out_fds++;
|
||||
|
||||
out_fds++;
|
||||
}
|
||||
|
||||
return nfds; // 0 on timeout or > 0 ..
|
||||
return nfds; // 0 on timeout or > 0 ..
|
||||
}//end: evdp_wait()
|
||||
|
||||
|
||||
void evdp_remove(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
if(ep->ev_added == true){
|
||||
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep->ev_data) != 0){
|
||||
ShowError("evdp [EPOLL]: evdp_remove - epoll_ctl (EPOLL_CTL_DEL) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
}
|
||||
|
||||
ep->ev_data.events = 0; // clear struct.
|
||||
ep->ev_data.data.fd = -1; // .. clear struct ..
|
||||
|
||||
ep->ev_added = false; // not added!
|
||||
if(ep->ev_added == true){
|
||||
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep->ev_data) != 0){
|
||||
ShowError("evdp [EPOLL]: evdp_remove - epoll_ctl (EPOLL_CTL_DEL) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
}
|
||||
|
||||
ep->ev_data.events = 0; // clear struct.
|
||||
ep->ev_data.data.fd = -1; // .. clear struct ..
|
||||
|
||||
ep->ev_added = false; // not added!
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//end: evdp_remove()
|
||||
|
||||
|
||||
bool evdp_addlistener(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
|
||||
ep->ev_data.events = EPOLLET|EPOLLIN;
|
||||
ep->ev_data.data.fd = fd;
|
||||
|
||||
|
||||
// No check here for 'added ?'
|
||||
// listeners cannot be added twice.
|
||||
//
|
||||
@ -106,47 +106,47 @@ bool evdp_addlistener(int32 fd, EVDP_DATA *ep){
|
||||
ep->ev_data.events = 0;
|
||||
ep->ev_data.data.fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ep->ev_added = true;
|
||||
|
||||
|
||||
return true;
|
||||
}//end: evdp_addlistener()
|
||||
|
||||
|
||||
bool evdp_addclient(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
|
||||
ep->ev_data.events = EPOLLIN | EPOLLHUP;
|
||||
ep->ev_data.data.fd = fd;
|
||||
|
||||
|
||||
// No check for "added?" here,
|
||||
// this function only gets called upon accpept.
|
||||
//
|
||||
|
||||
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){
|
||||
ShowError("evdp [EPOLL]: evdp_addclient - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
ep->ev_data.events = 0;
|
||||
ep->ev_data.data.fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ep->ev_added = true;
|
||||
|
||||
|
||||
return true;
|
||||
}//end: evdp_addclient()
|
||||
|
||||
|
||||
bool evdp_addconnecting(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
|
||||
ep->ev_data.events = EPOLLET | EPOLLOUT | EPOLLHUP;
|
||||
ep->ev_data.data.fd = fd;
|
||||
|
||||
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){
|
||||
ShowError("evdp [EPOLL]: evdp_addconnecting - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
ep->ev_data.events = 0;
|
||||
ep->ev_data.data.fd = -1;
|
||||
ep->ev_data.data.fd = -1;
|
||||
}
|
||||
|
||||
|
||||
ep->ev_added = true;
|
||||
|
||||
return true;
|
||||
@ -155,36 +155,36 @@ bool evdp_addconnecting(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep){
|
||||
int32 saved_mask;
|
||||
|
||||
|
||||
if(ep->ev_added != true){
|
||||
// !
|
||||
// !
|
||||
ShowError("evdp [EPOLL]: evdp_outgoingconnection_established fd #%u is not added to event dispatcher! invalid call.\n", fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
saved_mask = ep->ev_data.events;
|
||||
|
||||
|
||||
ep->ev_data.events = EPOLLIN | EPOLLHUP;
|
||||
|
||||
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){
|
||||
ep->ev_data.events = saved_mask; // restore old mask.
|
||||
ShowError("evdp [EPOLL]: evdp_outgoingconnection_established - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}//end: evdp_outgoingconnection_established()
|
||||
|
||||
|
||||
bool evdp_writable_add(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
|
||||
if(ep->ev_added != true){
|
||||
ShowError("evdp [EPOLL]: evdp_writable_add - tried to add not added fd #%u\n",fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! (ep->ev_data.events & EPOLLOUT) ){ //
|
||||
|
||||
|
||||
if(! (ep->ev_data.events & EPOLLOUT) ){ //
|
||||
|
||||
ep->ev_data.events |= EPOLLOUT;
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0 ){
|
||||
ShowError("evdp [EPOLL]: evdp_writable_add - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno: %u / %s)\n", fd, errno, strerror(errno));
|
||||
@ -192,27 +192,27 @@ bool evdp_writable_add(int32 fd, EVDP_DATA *ep){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}//end: evdp_writable_add()
|
||||
|
||||
|
||||
void evdp_writable_remove(int32 fd, EVDP_DATA *ep){
|
||||
|
||||
|
||||
if(ep->ev_added != true){
|
||||
ShowError("evdp [EPOLL]: evdp_writable_remove - tried to remove not added fd #%u\n", fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if( ep->ev_data.events & EPOLLOUT ){
|
||||
|
||||
|
||||
ep->ev_data.events &= ~EPOLLOUT;
|
||||
if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){
|
||||
ShowError("evdp [EPOLL]: evdp_writable_remove - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno));
|
||||
ep->ev_data.events |= EPOLLOUT; // add back to local flagmask because of failed syscall.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
return;
|
||||
}//end: evdp_writable_remove()
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
#if defined(MEMWATCH)
|
||||
|
||||
# include <string.h>
|
||||
# include <string.h>
|
||||
# include "memwatch.h"
|
||||
# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line))
|
||||
# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line))
|
||||
@ -231,7 +231,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
|
||||
ShowError("_mmalloc: %d\n", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
@ -375,7 +375,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
|
||||
struct unit_head *head;
|
||||
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long));
|
||||
if(head->size == 0) {
|
||||
|
||||
@ -53,7 +53,7 @@ struct ra_align(16) node{
|
||||
struct pool_segment{
|
||||
mempool pool; // pool, this segment belongs to
|
||||
struct pool_segment *next;
|
||||
int64 num_nodes_total;
|
||||
int64 num_nodes_total;
|
||||
int64 num_bytes;
|
||||
};
|
||||
|
||||
@ -64,7 +64,7 @@ struct mempool{
|
||||
uint64 elem_size;
|
||||
uint64 elem_realloc_step;
|
||||
int64 elem_realloc_thresh;
|
||||
|
||||
|
||||
// Callbacks that get called for every node that gets allocated
|
||||
// Example usage: initialization of mutex/lock for each node.
|
||||
memPoolOnNodeAllocationProc onalloc;
|
||||
@ -73,19 +73,19 @@ struct mempool{
|
||||
// Locks
|
||||
SPIN_LOCK segmentLock;
|
||||
SPIN_LOCK nodeLock;
|
||||
|
||||
|
||||
// Internal
|
||||
|
||||
// Internal
|
||||
struct pool_segment *segments;
|
||||
struct node *free_list;
|
||||
|
||||
|
||||
volatile int64 num_nodes_total;
|
||||
volatile int64 num_nodes_free;
|
||||
|
||||
volatile int64 num_segments;
|
||||
volatile int64 num_bytes_total;
|
||||
|
||||
volatile int64 peak_nodes_used; // Peak Node Usage
|
||||
|
||||
volatile int64 peak_nodes_used; // Peak Node Usage
|
||||
volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes)
|
||||
|
||||
// list (used for global management such as allocator..)
|
||||
@ -93,7 +93,7 @@ struct mempool{
|
||||
} ra_align(8); // Dont touch the alignment, otherwise interlocked functions are broken ..
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
// Implementation:
|
||||
//
|
||||
static void segment_allocate_add(mempool p, uint64 count);
|
||||
@ -107,33 +107,33 @@ static volatile int32 l_async_terminate = 0;
|
||||
|
||||
static void *mempool_async_allocator(void *x){
|
||||
mempool p;
|
||||
|
||||
|
||||
|
||||
|
||||
while(1){
|
||||
if(l_async_terminate > 0)
|
||||
break;
|
||||
|
||||
EnterSpinLock(&l_mempoolListLock);
|
||||
|
||||
|
||||
for(p = l_mempoolList; p != NULL; p = p->next){
|
||||
|
||||
|
||||
if(p->num_nodes_free < p->elem_realloc_thresh){
|
||||
// add new segment.
|
||||
segment_allocate_add(p, p->elem_realloc_step);
|
||||
// increase stats counter
|
||||
InterlockedIncrement64(&p->num_realloc_events);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
LeaveSpinLock(&l_mempoolListLock);
|
||||
|
||||
|
||||
ramutex_lock( l_async_lock );
|
||||
racond_wait( l_async_cond, l_async_lock, -1 );
|
||||
ramutex_unlock( l_async_lock );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return NULL;
|
||||
}//end: mempool_async_allocator()
|
||||
|
||||
@ -142,12 +142,12 @@ void mempool_init(){
|
||||
|
||||
if( rand()%2 + 1 )
|
||||
return;
|
||||
|
||||
|
||||
if(sizeof(struct node)%16 != 0 ){
|
||||
ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// Global List start
|
||||
InitializeSpinLock(&l_mempoolListLock);
|
||||
l_mempoolList = NULL;
|
||||
@ -168,23 +168,23 @@ void mempool_init(){
|
||||
|
||||
void mempool_final(){
|
||||
mempool p, pn;
|
||||
|
||||
|
||||
if( rand()%2 + 1 )
|
||||
return;
|
||||
|
||||
|
||||
ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n");
|
||||
|
||||
// Terminate worker / wait until its terminated.
|
||||
InterlockedIncrement(&l_async_terminate);
|
||||
racond_signal(l_async_cond);
|
||||
rathread_wait(l_async_thread, NULL);
|
||||
|
||||
|
||||
// Destroy cond var and mutex.
|
||||
racond_destroy( l_async_cond );
|
||||
ramutex_destroy( l_async_lock );
|
||||
|
||||
|
||||
// Free remaining mempools
|
||||
// ((bugged code! this should halppen, every mempool should
|
||||
// ((bugged code! this should halppen, every mempool should
|
||||
// be freed by the subsystem that has allocated it.)
|
||||
//
|
||||
EnterSpinLock(&l_mempoolListLock);
|
||||
@ -192,7 +192,7 @@ void mempool_final(){
|
||||
while(1){
|
||||
if(p == NULL)
|
||||
break;
|
||||
|
||||
|
||||
pn = p->next;
|
||||
|
||||
ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name);
|
||||
@ -201,28 +201,28 @@ void mempool_final(){
|
||||
p = pn;
|
||||
}
|
||||
LeaveSpinLock(&l_mempoolListLock);
|
||||
|
||||
|
||||
}//end: mempool_final()
|
||||
|
||||
|
||||
static void segment_allocate_add(mempool p, uint64 count){
|
||||
|
||||
|
||||
// Required Memory:
|
||||
// sz( segment )
|
||||
// sz( segment )
|
||||
// count * sz( real_node_size )
|
||||
//
|
||||
//
|
||||
// where real node size is:
|
||||
// ALIGN_TO_16( sz( node ) ) + p->elem_size
|
||||
// so the nodes usable address is nodebase + ALIGN_TO_16(sz(node))
|
||||
// ALIGN_TO_16( sz( node ) ) + p->elem_size
|
||||
// so the nodes usable address is nodebase + ALIGN_TO_16(sz(node))
|
||||
//
|
||||
size_t total_sz;
|
||||
struct pool_segment *seg = NULL;
|
||||
struct node *nodeList = NULL;
|
||||
struct node *node = NULL;
|
||||
char *ptr = NULL;
|
||||
char *ptr = NULL;
|
||||
uint64 i;
|
||||
|
||||
total_sz = ALIGN_TO_16( sizeof(struct pool_segment) )
|
||||
|
||||
total_sz = ALIGN_TO_16( sizeof(struct pool_segment) )
|
||||
+ ( (size_t)count * (sizeof(struct node) + (size_t)p->elem_size) ) ;
|
||||
|
||||
#ifdef MEMPOOL_DEBUG
|
||||
@ -234,7 +234,7 @@ static void segment_allocate_add(mempool p, uint64 count){
|
||||
while(1){
|
||||
ptr = (char*)aMalloc(total_sz);
|
||||
if(ptr != NULL) break;
|
||||
|
||||
|
||||
i++; // increase failcount.
|
||||
if(!(i & 7)){
|
||||
ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i);
|
||||
@ -244,29 +244,29 @@ static void segment_allocate_add(mempool p, uint64 count){
|
||||
sleep(1);
|
||||
#endif
|
||||
}else{
|
||||
rathread_yield(); /// allow/force vuln. ctxswitch
|
||||
rathread_yield(); /// allow/force vuln. ctxswitch
|
||||
}
|
||||
}//endwhile: allocation spinloop.
|
||||
|
||||
|
||||
// Clear Memory.
|
||||
memset(ptr, 0x00, total_sz);
|
||||
|
||||
|
||||
// Initialize segment struct.
|
||||
seg = (struct pool_segment*)ptr;
|
||||
ptr += ALIGN_TO_16(sizeof(struct pool_segment));
|
||||
|
||||
|
||||
seg->pool = p;
|
||||
seg->num_nodes_total = count;
|
||||
seg->num_bytes = total_sz;
|
||||
|
||||
|
||||
// Initialze nodes!
|
||||
nodeList = NULL;
|
||||
|
||||
|
||||
// Initialze nodes!
|
||||
nodeList = NULL;
|
||||
for(i = 0; i < count; i++){
|
||||
node = (struct node*)ptr;
|
||||
ptr += sizeof(struct node);
|
||||
ptr += p->elem_size;
|
||||
|
||||
|
||||
node->segment = seg;
|
||||
#ifdef MEMPOOLASSERT
|
||||
node->used = false;
|
||||
@ -277,16 +277,16 @@ static void segment_allocate_add(mempool p, uint64 count){
|
||||
|
||||
node->next = nodeList;
|
||||
nodeList = node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Link in Segment.
|
||||
EnterSpinLock(&p->segmentLock);
|
||||
seg->next = p->segments;
|
||||
p->segments = seg;
|
||||
LeaveSpinLock(&p->segmentLock);
|
||||
|
||||
|
||||
// Link in Nodes
|
||||
EnterSpinLock(&p->nodeLock);
|
||||
nodeList->next = p->free_list;
|
||||
@ -299,7 +299,7 @@ static void segment_allocate_add(mempool p, uint64 count){
|
||||
InterlockedExchangeAdd64(&p->num_nodes_free, count);
|
||||
InterlockedIncrement64(&p->num_segments);
|
||||
InterlockedExchangeAdd64(&p->num_bytes_total, total_sz);
|
||||
|
||||
|
||||
}//end: segment_allocate_add()
|
||||
|
||||
|
||||
@ -313,20 +313,20 @@ mempool mempool_create(const char *name,
|
||||
uint64 realloc_thresh;
|
||||
mempool pool;
|
||||
pool = (mempool)aCalloc( 1, sizeof(struct mempool) );
|
||||
|
||||
|
||||
if(pool == NULL){
|
||||
ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) );
|
||||
exit(EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// Check minimum initial count / realloc count requirements.
|
||||
if(initial_count < 50)
|
||||
initial_count = 50;
|
||||
if(realloc_count < 50)
|
||||
realloc_count = 50;
|
||||
|
||||
|
||||
// Set Reallocation threshold to 5% of realloc_count, at least 10.
|
||||
realloc_thresh = (realloc_count/100)*5; //
|
||||
realloc_thresh = (realloc_count/100)*5; //
|
||||
if(realloc_thresh < 10)
|
||||
realloc_thresh = 10;
|
||||
|
||||
@ -337,7 +337,7 @@ mempool mempool_create(const char *name,
|
||||
pool->elem_realloc_thresh = realloc_thresh;
|
||||
pool->onalloc = onNodeAlloc;
|
||||
pool->ondealloc = onNodeDealloc;
|
||||
|
||||
|
||||
InitializeSpinLock(&pool->segmentLock);
|
||||
InitializeSpinLock(&pool->nodeLock);
|
||||
|
||||
@ -348,15 +348,15 @@ mempool mempool_create(const char *name,
|
||||
pool->num_bytes_total = 0;
|
||||
pool->peak_nodes_used = 0;
|
||||
pool->num_realloc_events = 0;
|
||||
|
||||
|
||||
//
|
||||
#ifdef MEMPOOL_DEBUG
|
||||
ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step);
|
||||
#endif
|
||||
|
||||
// Allocate first segment directly :)
|
||||
// Allocate first segment directly :)
|
||||
segment_allocate_add(pool, initial_count);
|
||||
|
||||
|
||||
|
||||
// Add Pool to the global pool list
|
||||
EnterSpinLock(&l_mempoolListLock);
|
||||
@ -364,8 +364,8 @@ mempool mempool_create(const char *name,
|
||||
l_mempoolList = pool;
|
||||
LeaveSpinLock(&l_mempoolListLock);
|
||||
|
||||
|
||||
return pool;
|
||||
|
||||
return pool;
|
||||
}//end: mempool_create()
|
||||
|
||||
|
||||
@ -379,7 +379,7 @@ void mempool_destroy(mempool p){
|
||||
#ifdef MEMPOOL_DEBUG
|
||||
ShowDebug("Mempool [%s] Destroy\n", p->name);
|
||||
#endif
|
||||
|
||||
|
||||
// Unlink from global list.
|
||||
EnterSpinLock(&l_mempoolListLock);
|
||||
piter = l_mempoolList;
|
||||
@ -387,11 +387,11 @@ void mempool_destroy(mempool p){
|
||||
while(1){
|
||||
if(piter == NULL)
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
if(piter == p){
|
||||
// unlink from list,
|
||||
//
|
||||
//
|
||||
if(pprev == l_mempoolList){
|
||||
// this (p) is list begin. so set next as head.
|
||||
l_mempoolList = p->next;
|
||||
@ -401,15 +401,15 @@ void mempool_destroy(mempool p){
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pprev = piter;
|
||||
|
||||
pprev = piter;
|
||||
piter = piter->next;
|
||||
}
|
||||
|
||||
p->next = NULL;
|
||||
LeaveSpinLock(&l_mempoolListLock);
|
||||
|
||||
|
||||
|
||||
|
||||
// Get both locks.
|
||||
EnterSpinLock(&p->segmentLock);
|
||||
EnterSpinLock(&p->nodeLock);
|
||||
@ -417,16 +417,16 @@ void mempool_destroy(mempool p){
|
||||
|
||||
if(p->num_nodes_free != p->num_nodes_total)
|
||||
ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free) );
|
||||
|
||||
|
||||
// Free All Segments (this will also free all nodes)
|
||||
// The segment pointer is the base pointer to the whole segment.
|
||||
seg = p->segments;
|
||||
while(1){
|
||||
if(seg == NULL)
|
||||
break;
|
||||
|
||||
|
||||
segnext = seg->next;
|
||||
|
||||
|
||||
// ..
|
||||
if(p->ondealloc != NULL){
|
||||
// walk over the segment, and call dealloc callback!
|
||||
@ -442,26 +442,26 @@ void mempool_destroy(mempool p){
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
p->ondealloc( NODE_TO_DATA(niter) );
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}//endif: ondealloc callback?
|
||||
|
||||
|
||||
// simple ..
|
||||
aFree(seg);
|
||||
|
||||
|
||||
seg = segnext;
|
||||
}
|
||||
|
||||
// Clear node ptr
|
||||
|
||||
// Clear node ptr
|
||||
p->free_list = NULL;
|
||||
InterlockedExchange64(&p->num_nodes_free, 0);
|
||||
InterlockedExchange64(&p->num_nodes_free, 0);
|
||||
InterlockedExchange64(&p->num_nodes_total, 0);
|
||||
InterlockedExchange64(&p->num_segments, 0);
|
||||
InterlockedExchange64(&p->num_bytes_total, 0);
|
||||
|
||||
|
||||
LeaveSpinLock(&p->nodeLock);
|
||||
LeaveSpinLock(&p->segmentLock);
|
||||
|
||||
@ -475,34 +475,34 @@ void mempool_destroy(mempool p){
|
||||
void *mempool_node_get(mempool p){
|
||||
struct node *node;
|
||||
int64 num_used;
|
||||
|
||||
|
||||
if(p->num_nodes_free < p->elem_realloc_thresh)
|
||||
racond_signal(l_async_cond);
|
||||
|
||||
|
||||
while(1){
|
||||
|
||||
EnterSpinLock(&p->nodeLock);
|
||||
|
||||
|
||||
node = p->free_list;
|
||||
if(node != NULL)
|
||||
p->free_list = node->next;
|
||||
|
||||
|
||||
LeaveSpinLock(&p->nodeLock);
|
||||
|
||||
if(node != NULL)
|
||||
break;
|
||||
|
||||
|
||||
rathread_yield();
|
||||
}
|
||||
|
||||
InterlockedDecrement64(&p->num_nodes_free);
|
||||
|
||||
|
||||
// Update peak value
|
||||
num_used = (p->num_nodes_total - p->num_nodes_free);
|
||||
if(num_used > p->peak_nodes_used){
|
||||
InterlockedExchange64(&p->peak_nodes_used, num_used);
|
||||
}
|
||||
|
||||
|
||||
#ifdef MEMPOOLASSERT
|
||||
node->used = true;
|
||||
#endif
|
||||
@ -513,12 +513,12 @@ void *mempool_node_get(mempool p){
|
||||
|
||||
void mempool_node_put(mempool p, void *data){
|
||||
struct node *node;
|
||||
|
||||
|
||||
node = DATA_TO_NODE(data);
|
||||
#ifdef MEMPOOLASSERT
|
||||
if(node->magic != NODE_MAGIC){
|
||||
ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data);
|
||||
return; // lost,
|
||||
return; // lost,
|
||||
}
|
||||
|
||||
{
|
||||
@ -528,17 +528,17 @@ void mempool_node_put(mempool p, void *data){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// reset used flag.
|
||||
node->used = false;
|
||||
#endif
|
||||
|
||||
//
|
||||
//
|
||||
EnterSpinLock(&p->nodeLock);
|
||||
node->next = p->free_list;
|
||||
p->free_list = node;
|
||||
LeaveSpinLock(&p->nodeLock);
|
||||
|
||||
|
||||
InterlockedIncrement64(&p->num_nodes_free);
|
||||
|
||||
}//end: mempool_node_put()
|
||||
@ -546,10 +546,10 @@ void mempool_node_put(mempool p, void *data){
|
||||
|
||||
mempool_stats mempool_get_stats(mempool pool){
|
||||
mempool_stats stats;
|
||||
|
||||
|
||||
// initialize all with zeros
|
||||
memset(&stats, 0x00, sizeof(mempool_stats));
|
||||
|
||||
|
||||
stats.num_nodes_total = pool->num_nodes_total;
|
||||
stats.num_nodes_free = pool->num_nodes_free;
|
||||
stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free);
|
||||
@ -560,7 +560,7 @@ mempool_stats mempool_get_stats(mempool pool){
|
||||
|
||||
// Pushing such a large block over the stack as return value isnt nice
|
||||
// but lazy :) and should be okay in this case (Stats / Debug..)
|
||||
// if you dont like it - feel free and refactor it.
|
||||
// if you dont like it - feel free and refactor it.
|
||||
return stats;
|
||||
}//end: mempool_get_stats()
|
||||
|
||||
|
||||
@ -12,33 +12,33 @@ typedef struct mempool_stats{
|
||||
int64 num_nodes_total;
|
||||
int64 num_nodes_free;
|
||||
int64 num_nodes_used;
|
||||
|
||||
|
||||
int64 num_segments;
|
||||
int64 num_realloc_events;
|
||||
|
||||
|
||||
int64 peak_nodes_used;
|
||||
|
||||
|
||||
int64 num_bytes_total;
|
||||
} mempool_stats;
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
void mempool_init();
|
||||
void mempool_final();
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a new Mempool
|
||||
*
|
||||
* @param name - Name of the pool (used for debug / error messages)
|
||||
* @param elem_size - size of each element
|
||||
* @param initial_count - preallocation count
|
||||
* @param initial_count - preallocation count
|
||||
* @param realloc_count - #no of nodes being allocated when pool is running empty.
|
||||
* @param onNodeAlloc - Node Allocation callback (see @note!)
|
||||
* @param onNodeDealloc - Node Deallocation callback (see @note!)
|
||||
*
|
||||
* @note:
|
||||
* The onNode(De)alloc callbacks are only called once during segment allocation
|
||||
* The onNode(De)alloc callbacks are only called once during segment allocation
|
||||
* (pool initialization / rallocation )
|
||||
* you can use this callbacks for example to initlaize a mutex or somethingelse
|
||||
* you definitly need during runtime
|
||||
@ -49,14 +49,14 @@ mempool mempool_create(const char *name,
|
||||
uint64 elem_size,
|
||||
uint64 initial_count,
|
||||
uint64 realloc_count,
|
||||
|
||||
|
||||
memPoolOnNodeAllocationProc onNodeAlloc,
|
||||
memPoolOnNodeDeallocationProc onNodeDealloc);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Destroys a Mempool
|
||||
*
|
||||
*
|
||||
* @param pool - the mempool to destroy
|
||||
*
|
||||
* @note:
|
||||
@ -68,7 +68,7 @@ void mempool_destroy(mempool pool);
|
||||
|
||||
/**
|
||||
* Gets a new / empty node from the given mempool.
|
||||
*
|
||||
*
|
||||
* @param pool - the pool to get an empty node from.
|
||||
*
|
||||
* @return Address of empty Node
|
||||
@ -80,12 +80,12 @@ void *mempool_node_get(mempool pool);
|
||||
* Returns the given node to the given mempool
|
||||
*
|
||||
* @param pool - the pool to put the node, to
|
||||
* @param node - the node to return
|
||||
* @param node - the node to return
|
||||
*/
|
||||
void mempool_node_put(mempool pool, void *node);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns Statistics for the given mempool
|
||||
*
|
||||
* @param pool - the pool to get thats for
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
#define MAX_INVENTORY 100 ///Maximum items in player inventory
|
||||
/** 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.
|
||||
* Max value tested was 265 */
|
||||
#define MAX_CHARS 9
|
||||
#define MAX_CHARS 9
|
||||
/** Number of slots carded equipment can have. Never set to less than 4 as they are also used to keep the data of forged items/equipment. [Skotlex]
|
||||
* Note: The client seems unable to receive data for more than 4 slots due to all related packets having a fixed size. */
|
||||
#define MAX_SLOTS 4
|
||||
|
||||
@ -47,19 +47,19 @@ struct racond{
|
||||
|
||||
ramutex ramutex_create(){
|
||||
struct ramutex *m;
|
||||
|
||||
|
||||
m = (struct ramutex*)aMalloc( sizeof(struct ramutex) );
|
||||
if(m == NULL){
|
||||
ShowFatalError("ramutex_create: OOM while allocating %u bytes.\n", sizeof(struct ramutex));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
InitializeCriticalSection(&m->hMutex);
|
||||
#else
|
||||
pthread_mutex_init(&m->hMutex, NULL);
|
||||
#endif
|
||||
|
||||
|
||||
return m;
|
||||
}//end: ramutex_create()
|
||||
|
||||
@ -96,7 +96,7 @@ bool ramutex_trylock( ramutex m ){
|
||||
#else
|
||||
if(pthread_mutex_trylock(&m->hMutex) == 0)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}//end: ramutex_trylock()
|
||||
@ -115,13 +115,13 @@ void ramutex_unlock( ramutex m ){
|
||||
|
||||
///////////////
|
||||
// Condition Variables
|
||||
//
|
||||
//
|
||||
// Implementation:
|
||||
//
|
||||
|
||||
racond racond_create(){
|
||||
struct racond *c;
|
||||
|
||||
|
||||
c = (struct racond*)aMalloc( sizeof(struct racond) );
|
||||
if(c == NULL){
|
||||
ShowFatalError("racond_create: OOM while allocating %u bytes\n", sizeof(struct racond));
|
||||
@ -136,7 +136,7 @@ racond racond_create(){
|
||||
#else
|
||||
pthread_cond_init(&c->hCond, NULL);
|
||||
#endif
|
||||
|
||||
|
||||
return c;
|
||||
}//end: racond_create()
|
||||
|
||||
@ -169,23 +169,23 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks){
|
||||
ms = INFINITE;
|
||||
else
|
||||
ms = (timeout_ticks > MAXDWORD) ? (MAXDWORD - 1) : (DWORD)timeout_ticks;
|
||||
|
||||
|
||||
|
||||
|
||||
// we can release the mutex (m) here, cause win's
|
||||
// manual reset events maintain state when used with
|
||||
// SetEvent()
|
||||
ramutex_unlock(m);
|
||||
|
||||
result = WaitForMultipleObjects(2, c->events, FALSE, ms);
|
||||
|
||||
|
||||
|
||||
|
||||
EnterCriticalSection(&c->waiters_lock);
|
||||
c->nWaiters--;
|
||||
if( (result == WAIT_OBJECT_0 + EVENT_COND_BROADCAST) && (c->nWaiters == 0) )
|
||||
is_last = true; // Broadcast called!
|
||||
LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
|
||||
|
||||
|
||||
// we are the last waiter that has to be notified, or to stop waiting
|
||||
// so we have to do a manual reset
|
||||
@ -201,10 +201,10 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks){
|
||||
}else{
|
||||
struct timespec wtime;
|
||||
int64 exact_timeout = gettick() + timeout_ticks;
|
||||
|
||||
|
||||
wtime.tv_sec = exact_timeout/1000;
|
||||
wtime.tv_nsec = (exact_timeout%1000)*1000000;
|
||||
|
||||
|
||||
pthread_cond_timedwait( &c->hCond, &m->hMutex, &wtime);
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ void racond_signal( racond c ){
|
||||
// if(c->nWaiters > 0)
|
||||
// has_waiters = true;
|
||||
// LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
|
||||
// if(has_waiters == true)
|
||||
SetEvent( c->events[ EVENT_COND_SIGNAL ] );
|
||||
#else
|
||||
@ -235,7 +235,7 @@ void racond_broadcast( racond c ){
|
||||
// if(c->nWaiters > 0)
|
||||
// has_waiters = true;
|
||||
// LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
|
||||
// if(has_waiters == true)
|
||||
SetEvent( c->events[ EVENT_COND_BROADCAST ] );
|
||||
#else
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#ifndef _rA_MUTEX_H_
|
||||
#define _rA_MUTEX_H_
|
||||
@ -9,36 +9,36 @@ typedef struct ramutex *ramutex; // Mutex
|
||||
typedef struct racond *racond; // Condition Var
|
||||
|
||||
/**
|
||||
* Creates a Mutex
|
||||
* Creates a Mutex
|
||||
*
|
||||
* @return not NULL
|
||||
*/
|
||||
ramutex ramutex_create();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Destroys a Mutex
|
||||
*
|
||||
*
|
||||
* @param m - the mutex to destroy
|
||||
*/
|
||||
void ramutex_destroy( ramutex m );
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets a lock
|
||||
*
|
||||
* @param m - the mutex to lock
|
||||
*/
|
||||
void ramutex_lock( ramutex m);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Trys to get the Lock
|
||||
*
|
||||
*
|
||||
* @param m - the mutex try to lock
|
||||
*
|
||||
*
|
||||
* @return boolean (true = got the lock)
|
||||
*/
|
||||
bool ramutex_trylock( ramutex m );
|
||||
|
||||
/**
|
||||
/**
|
||||
* Unlocks a mutex
|
||||
*
|
||||
* @param m - the mutex to unlock
|
||||
@ -46,14 +46,14 @@ bool ramutex_trylock( ramutex m );
|
||||
void ramutex_unlock( ramutex m);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a Condition variable
|
||||
*
|
||||
* @return not NULL
|
||||
*/
|
||||
racond racond_create();
|
||||
|
||||
/**
|
||||
/**
|
||||
* Destroy a Condition variable
|
||||
*
|
||||
* @param c - the condition varaible to destroy
|
||||
@ -62,14 +62,14 @@ void racond_destroy( racond c );
|
||||
|
||||
/**
|
||||
* Waits Until state is signalled
|
||||
*
|
||||
* @param c - the condition var to wait for signalled state
|
||||
*
|
||||
* @param c - the condition var to wait for signalled state
|
||||
* @param m - the mutex used for syncronization
|
||||
* @param timeout_ticks - timeout in ticks ( -1 = INFINITE )
|
||||
*/
|
||||
void racond_wait( racond c, ramutex m, sysint timeout_ticks);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the given condition var to signalled state
|
||||
*
|
||||
* @param c - condition var to set in signalled state.
|
||||
@ -79,13 +79,13 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks);
|
||||
*/
|
||||
void racond_signal( racond c );
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets notifys all waiting threads thats signalled.
|
||||
* @param c - condition var to set in signalled state
|
||||
*
|
||||
*
|
||||
* @note:
|
||||
* All Waiters getting notified.
|
||||
*/
|
||||
*/
|
||||
void racond_broadcast( racond c );
|
||||
|
||||
|
||||
|
||||
@ -11,10 +11,10 @@
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Buffers are available in the following sizes:
|
||||
// 48, 192, 2048, 8192
|
||||
// 65536 (inter server connects may use it for charstatus struct..)
|
||||
// 65536 (inter server connects may use it for charstatus struct..)
|
||||
//
|
||||
|
||||
|
||||
@ -31,10 +31,10 @@ void netbuffer_init(){
|
||||
char localsection[32];
|
||||
raconf conf;
|
||||
sysint i;
|
||||
|
||||
|
||||
// Initialize Statistic counters:
|
||||
l_nEmergencyAllocations = 0;
|
||||
|
||||
|
||||
// Set localsection name according to running serverype.
|
||||
switch(SERVER_TYPE){
|
||||
case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break;
|
||||
@ -43,49 +43,49 @@ void netbuffer_init(){
|
||||
case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break;
|
||||
default: strcpy(localsection, "unsupported_type"); break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
conf = raconf_parse("conf/network.conf");
|
||||
if(conf == NULL){
|
||||
ShowFatalError("Failed to Parse required Configuration (conf/network.conf)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// Get Values from config file
|
||||
l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0);
|
||||
if(l_nPools == 0){
|
||||
ShowFatalError("Netbuffer (network.conf) failure - requires at least 1 Pool.\n");
|
||||
ShowFatalError("Netbuffer (network.conf) failure - requires at least 1 Pool.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate arrays.
|
||||
l_poolElemSize = (sysint*)aCalloc( l_nPools, sizeof(sysint) );
|
||||
l_pool = (mempool*)aCalloc( l_nPools, sizeof(mempool) );
|
||||
|
||||
|
||||
|
||||
for(i = 0; i < l_nPools; i++){
|
||||
int64 num_prealloc, num_realloc;
|
||||
char key[32];
|
||||
|
||||
|
||||
sprintf(key, "pool_%u_size", (uint32)i+1);
|
||||
l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096);
|
||||
if(l_poolElemSize[i] < 32){
|
||||
ShowWarning("Netbuffer (network.conf) failure - minimum allowed buffer size is 32 byte) - fixed.\n");
|
||||
l_poolElemSize[i] = 32;
|
||||
}
|
||||
|
||||
|
||||
sprintf(key, "pool_%u_prealloc", (uint32)i+1);
|
||||
num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150);
|
||||
|
||||
|
||||
sprintf(key, "pool_%u_realloc_step", (uint32)i+1);
|
||||
num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100);
|
||||
|
||||
|
||||
// Create Pool!
|
||||
sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name.
|
||||
|
||||
// Info
|
||||
ShowInfo("NetBuffer: Creating Pool %u (Prealloc: %u, Realloc Step: %u) - %0.2f MiB\n", l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f);
|
||||
|
||||
|
||||
//
|
||||
// Size Calculation:
|
||||
// struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct)
|
||||
@ -94,11 +94,11 @@ void netbuffer_init(){
|
||||
ShowFatalError("Netbuffer: cannot create Pool for %u byte buffers.\n", l_poolElemSize[i]);
|
||||
// @leak: clean everything :D
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}//
|
||||
|
||||
|
||||
}
|
||||
|
||||
}//
|
||||
|
||||
|
||||
raconf_destroy(conf);
|
||||
|
||||
}//end: netbuffer_init()
|
||||
@ -106,58 +106,58 @@ void netbuffer_init(){
|
||||
|
||||
void netbuffer_final(){
|
||||
sysint i;
|
||||
|
||||
|
||||
if(l_nPools > 0){
|
||||
/// .. finalize mempools
|
||||
for(i = 0; i < l_nPools; i++){
|
||||
mempool_stats stats = mempool_get_stats(l_pool[i]);
|
||||
|
||||
|
||||
ShowInfo("Netbuffer: Freeing Pool %u (Peak Usage: %u, Realloc Events: %u)\n", l_poolElemSize[i], stats.peak_nodes_used, stats.num_realloc_events);
|
||||
|
||||
|
||||
mempool_destroy(l_pool[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(l_nEmergencyAllocations > 0){
|
||||
ShowWarning("Netbuffer: did %u Emergency Allocations, please tune your network.conf!\n", l_nEmergencyAllocations);
|
||||
l_nEmergencyAllocations = 0;
|
||||
}
|
||||
|
||||
|
||||
aFree(l_poolElemSize); l_poolElemSize = NULL;
|
||||
aFree(l_pool); l_pool = NULL;
|
||||
l_nPools = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}//end: netbuffer_final()
|
||||
|
||||
|
||||
netbuf netbuffer_get( sysint sz ){
|
||||
sysint i;
|
||||
netbuf nb = NULL;
|
||||
|
||||
|
||||
// Search an appropriate pool
|
||||
for(i = 0; i < l_nPools; i++){
|
||||
if(sz <= l_poolElemSize[i]){
|
||||
// match
|
||||
|
||||
nb = (netbuf)mempool_node_get(l_pool[i]);
|
||||
// match
|
||||
|
||||
nb = (netbuf)mempool_node_get(l_pool[i]);
|
||||
nb->pool = i;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No Bufferpool found that mets there quirements?.. (thats bad..)
|
||||
if(nb == NULL){
|
||||
ShowWarning("Netbuffer: get(%u): => no appropriate pool found - emergency allocation required.\n", sz);
|
||||
ShowWarning("Please reconfigure your network.conf!");
|
||||
|
||||
|
||||
InterlockedIncrement(&l_nEmergencyAllocations);
|
||||
|
||||
// .. better to check (netbuf struct provides 32 byte bufferspace itself.
|
||||
if(sz < 32) sz = 32;
|
||||
|
||||
// allocate memory using malloc ..
|
||||
|
||||
// allocate memory using malloc ..
|
||||
while(1){
|
||||
nb = (netbuf) aMalloc( (sizeof(struct netbuf) + sz - 32) );
|
||||
if(nb != NULL){
|
||||
@ -165,42 +165,42 @@ netbuf netbuffer_get( sysint sz ){
|
||||
nb->pool = -1; // emergency alloc.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
rathread_yield();
|
||||
}// spin allocation.
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nb->refcnt = 1; // Initial refcount is 1
|
||||
|
||||
return nb;
|
||||
return nb;
|
||||
}//end: netbuffer_get()
|
||||
|
||||
|
||||
void netbuffer_put( netbuf nb ){
|
||||
|
||||
|
||||
// Decrement reference counter, if > 0 do nothing :)
|
||||
if( InterlockedDecrement(&nb->refcnt) > 0 )
|
||||
return;
|
||||
|
||||
|
||||
// Is this buffer an emergency allocated buffer?
|
||||
if(nb->pool == -1){
|
||||
aFree(nb);
|
||||
aFree(nb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Otherwise its a normal mempool based buffer
|
||||
// return it to the according mempool:
|
||||
mempool_node_put( l_pool[nb->pool], nb);
|
||||
|
||||
|
||||
|
||||
|
||||
}//end: netbuffer_put()
|
||||
|
||||
|
||||
void netbuffer_incref( netbuf nb ){
|
||||
|
||||
|
||||
InterlockedIncrement(&nb->refcnt);
|
||||
|
||||
|
||||
}//end: netbuf_incref()
|
||||
|
||||
@ -8,11 +8,11 @@
|
||||
|
||||
typedef struct netbuf{
|
||||
sysint pool; // The pool ID this buffer belongs to,
|
||||
// is set to -1 if its an emergency allocated buffer
|
||||
|
||||
// is set to -1 if its an emergency allocated buffer
|
||||
|
||||
struct netbuf *next; // Used by Network system.
|
||||
|
||||
volatile int32 refcnt; // Internal Refcount, it gets lowered every call to netbuffer_put,
|
||||
volatile int32 refcnt; // Internal Refcount, it gets lowered every call to netbuffer_put,
|
||||
// if its getting zero, the buffer will returned back to the pool
|
||||
// and can be reused.
|
||||
|
||||
@ -20,7 +20,7 @@ typedef struct netbuf{
|
||||
// Used only for Reading (recv job)
|
||||
// write cases are using the sessions local datapos member due to
|
||||
// shared write buffer support.
|
||||
|
||||
|
||||
int32 dataLen; // read buffer case:
|
||||
// The length expected to read to.
|
||||
// when this->dataPos == dateLen, read job has been completed.
|
||||
@ -56,16 +56,16 @@ void netbuffer_final();
|
||||
netbuf netbuffer_get( sysint sz );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the given netbuffer (decreases refcount, if its 0 - the buffer will get returned to the pool)
|
||||
*
|
||||
* @param buf - the buffer to return
|
||||
* @param buf - the buffer to return
|
||||
*/
|
||||
void netbuffer_put( netbuf buf );
|
||||
|
||||
|
||||
/**
|
||||
* Increases the Refcount on the given buffer
|
||||
/**
|
||||
* Increases the Refcount on the given buffer
|
||||
* (used for areasends .. etc)
|
||||
*
|
||||
*/
|
||||
|
||||
@ -43,22 +43,22 @@ static int _network_async_free_netbuf_proc(int tid, unsigned int tick, int id, i
|
||||
void network_init(){
|
||||
SESSION *s;
|
||||
int32 i;
|
||||
|
||||
|
||||
memset(g_Session, 0x00, (sizeof(SESSION) * MAXCONN) );
|
||||
|
||||
|
||||
for(i = 0; i < MAXCONN; i++){
|
||||
s = &g_Session[i];
|
||||
|
||||
s->type = NST_FREE;
|
||||
s->disconnect_in_progress = false;
|
||||
}
|
||||
|
||||
|
||||
// Initialize the corresponding event dispatcher
|
||||
evdp_init();
|
||||
|
||||
//
|
||||
add_timer_func_list(_network_async_free_netbuf_proc, "_network_async_free_netbuf_proc");
|
||||
|
||||
|
||||
}//end: network_init()
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ void network_final(){
|
||||
|
||||
// @TODO:
|
||||
// .. disconnect and cleanup everything!
|
||||
|
||||
|
||||
evdp_final();
|
||||
|
||||
}//end: network_final()
|
||||
@ -77,21 +77,21 @@ void network_do(){
|
||||
register struct EVDP_EVENT *ev;
|
||||
register int n, nfds;
|
||||
register SESSION *s;
|
||||
|
||||
|
||||
nfds = evdp_wait( l_events, EVENTS_PER_CYCLE, 1000); // @TODO: timer_getnext()
|
||||
|
||||
|
||||
for(n = 0; n < nfds; n++){
|
||||
ev = &l_events[n];
|
||||
s = &g_Session[ ev->fd ];
|
||||
|
||||
|
||||
if(ev->events & EVDP_EVENT_HUP){
|
||||
network_disconnect( ev->fd );
|
||||
network_disconnect( ev->fd );
|
||||
continue; // no further event processing.
|
||||
}// endif vent is HUP (disconnect)
|
||||
|
||||
|
||||
|
||||
|
||||
if(ev->events & EVDP_EVENT_IN){
|
||||
|
||||
|
||||
if(s->onRecv != NULL){
|
||||
if( false == s->onRecv(ev->fd) ){
|
||||
network_disconnect(ev->fd);
|
||||
@ -101,11 +101,11 @@ void network_do(){
|
||||
ShowError("network_do: fd #%u has no onRecv proc set. - disconnecting\n", ev->fd);
|
||||
network_disconnect(ev->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}// endif event is IN (recv)
|
||||
|
||||
|
||||
|
||||
|
||||
if(ev->events & EVDP_EVENT_OUT){
|
||||
if(s->onSend != NULL){
|
||||
if( false == s->onSend(ev->fd) ){
|
||||
@ -118,9 +118,9 @@ void network_do(){
|
||||
continue;
|
||||
}
|
||||
}// endif event is OUT (send)
|
||||
|
||||
|
||||
}//endfor
|
||||
|
||||
|
||||
}//end: network_do()
|
||||
|
||||
|
||||
@ -135,7 +135,7 @@ static bool _setnonblock(int32 fd){
|
||||
|
||||
static bool _network_accept(int32 fd){
|
||||
SESSION *listener = &g_Session[fd];
|
||||
SESSION *s;
|
||||
SESSION *s;
|
||||
union{
|
||||
struct sockaddr_in v4;
|
||||
#ifdef ENABLE_IPV6
|
||||
@ -156,7 +156,7 @@ static bool _network_accept(int32 fd){
|
||||
}else{
|
||||
#endif
|
||||
addrlen = sizeof(_addr.v4);
|
||||
addr = (struct sockaddr*)&_addr.v4;
|
||||
addr = (struct sockaddr*)&_addr.v4;
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
@ -170,9 +170,9 @@ static bool _network_accept(int32 fd){
|
||||
if(newfd == -1){
|
||||
if(errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
break; // this is fully valid & whished., se explaination on top of while(1)
|
||||
|
||||
|
||||
// Otherwis .. we have serious problems :( seems tahat our listner has gone away..
|
||||
// @TODO handle this ..
|
||||
// @TODO handle this ..
|
||||
ShowError("_network_accept: accept() returned error. closing listener. (errno: %u / %s)\n", errno, strerror(errno));
|
||||
|
||||
return false; // will call disconnect after return.
|
||||
@ -183,7 +183,7 @@ static bool _network_accept(int32 fd){
|
||||
if(_setnonblock(newfd) == false){
|
||||
ShowError("_network_accept: failed to set newly accepted connection nonblocking (errno: %u / %s). - disconnecting.\n", errno, strerror(errno));
|
||||
close(newfd);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -198,31 +198,31 @@ static bool _network_accept(int32 fd){
|
||||
// Create new Session.
|
||||
s = &g_Session[newfd];
|
||||
s->type = NST_CLIENT;
|
||||
|
||||
|
||||
// The new connection inherits listenr's handlers.
|
||||
s->onDisconnect = listener->onDisconnect;
|
||||
s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~
|
||||
|
||||
s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~
|
||||
|
||||
// Register the new connection @ EVDP
|
||||
if( evdp_addclient(newfd, &s->evdp_data) == false){
|
||||
ShowError("_network_accept: failed to accept connection - event subsystem returned an error.\n");
|
||||
close(newfd);
|
||||
s->type = NST_FREE;
|
||||
}
|
||||
|
||||
|
||||
// Call the onConnect handler on the listener.
|
||||
if( listener->onConnect(newfd) == false ){
|
||||
// Resfused by onConnect handler..
|
||||
evdp_remove(newfd, &s->evdp_data);
|
||||
|
||||
|
||||
close(newfd);
|
||||
s->type = NST_FREE;
|
||||
|
||||
|
||||
s->data = NULL; // be on the safe side ~ !
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -232,30 +232,30 @@ static bool _network_accept(int32 fd){
|
||||
void network_disconnect(int32 fd){
|
||||
SESSION *s = &g_Session[fd];
|
||||
netbuf b, bn;
|
||||
|
||||
// Prevent recursive calls
|
||||
|
||||
// Prevent recursive calls
|
||||
// by wrong implemented on disconnect handlers.. and such..
|
||||
if(s->disconnect_in_progress == true)
|
||||
return;
|
||||
|
||||
return;
|
||||
|
||||
s->disconnect_in_progress = true;
|
||||
|
||||
|
||||
|
||||
|
||||
// Disconnect Todo:
|
||||
// - Call onDisconnect Handler
|
||||
// - Release all Assigned buffers.
|
||||
// - remove from event system (notifications)
|
||||
// - cleanup session structure
|
||||
// - close connection.
|
||||
// - close connection.
|
||||
//
|
||||
|
||||
if(s->onDisconnect != NULL &&
|
||||
|
||||
if(s->onDisconnect != NULL &&
|
||||
s->type != NST_LISTENER){
|
||||
|
||||
|
||||
s->onDisconnect( fd );
|
||||
}
|
||||
|
||||
// Read Buffer
|
||||
// Read Buffer
|
||||
if(s->read.buf != NULL){
|
||||
netbuffer_put(s->read.buf);
|
||||
s->read.buf = NULL;
|
||||
@ -267,30 +267,30 @@ void network_disconnect(int32 fd){
|
||||
if(b == NULL) break;
|
||||
|
||||
bn = b->next;
|
||||
|
||||
|
||||
netbuffer_put(b);
|
||||
|
||||
|
||||
b = bn;
|
||||
}
|
||||
s->write.buf = NULL;
|
||||
s->write.buf_last = NULL;
|
||||
|
||||
|
||||
s->write.n_outstanding = 0;
|
||||
s->write.max_outstanding = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// Remove from event system.
|
||||
evdp_remove(fd, &s->evdp_data);
|
||||
|
||||
|
||||
// Cleanup Session Structure.
|
||||
s->type = NST_FREE;
|
||||
s->data = NULL; // no application level data assigned
|
||||
s->disconnect_in_progress = false;
|
||||
|
||||
|
||||
// Close connection
|
||||
close(fd);
|
||||
|
||||
// Close connection
|
||||
close(fd);
|
||||
|
||||
}//end: network_disconnect()
|
||||
|
||||
|
||||
@ -320,7 +320,7 @@ int32 network_addlistener(bool v6, const char *addr, uint16 port){
|
||||
ShowError("network_addlistener(%c, '%s', %u): socket() failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Too many connections?
|
||||
if(fd >= MAXCONN){
|
||||
ShowError("network_addlistener(%c, '%s', %u): cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'), addr, port, MAXCONN);
|
||||
@ -377,7 +377,7 @@ int32 network_addlistener(bool v6, const char *addr, uint16 port){
|
||||
ShowError("network_addlistener(f, '%s', %u): bind failed (errno: %u / %s)\n", addr, port, errno, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
@ -387,14 +387,14 @@ int32 network_addlistener(bool v6, const char *addr, uint16 port){
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set to nonblock!
|
||||
if(_setnonblock(fd) == false){
|
||||
ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Rgister @ evdp.
|
||||
if( evdp_addlistener(fd, &s->evdp_data) != true){
|
||||
@ -406,7 +406,7 @@ int32 network_addlistener(bool v6, const char *addr, uint16 port){
|
||||
// Apply flags on Session array for this conneciton.
|
||||
if(v6 == true) s->v6 = true;
|
||||
else s->v6 = false;
|
||||
|
||||
|
||||
s->type = NST_LISTENER;
|
||||
s->onRecv = _network_accept;
|
||||
|
||||
@ -420,16 +420,16 @@ static bool _network_connect_establishedHandler(int32 fd){
|
||||
register SESSION *s = &g_Session[fd];
|
||||
int val;
|
||||
socklen_t val_len;
|
||||
|
||||
|
||||
if(s->type == NST_FREE)
|
||||
return true; // due to multiple non coalesced event notifications
|
||||
// this can happen .. when a previous handled event has already disconnected the connection
|
||||
// within the same cycle..
|
||||
|
||||
|
||||
val = -1;
|
||||
val_len = sizeof(val);
|
||||
getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &val_len);
|
||||
|
||||
|
||||
if(val != 0){
|
||||
// :( .. cleanup session..
|
||||
s->type = NST_FREE;
|
||||
@ -439,37 +439,37 @@ static bool _network_connect_establishedHandler(int32 fd){
|
||||
|
||||
evdp_remove(fd, &s->evdp_data);
|
||||
close(fd);
|
||||
|
||||
|
||||
return true; // we CANT return false,
|
||||
// becuase the normal disconnect procedure would execute the ondisconnect handler, which we dont want .. in this case.
|
||||
}else{
|
||||
// ok
|
||||
// ok
|
||||
if(s->onConnect(fd) == false) {
|
||||
// onConnect handler has refused the connection ..
|
||||
// onConnect handler has refused the connection ..
|
||||
// cleanup .. and ok
|
||||
s->type = NST_FREE;
|
||||
s->onSend = NULL;
|
||||
s->onConnect = NULL;
|
||||
s->onDisconnect = NULL;
|
||||
|
||||
|
||||
evdp_remove(fd, &s->evdp_data);
|
||||
close(fd);
|
||||
|
||||
|
||||
return true; // we dnot want the ondisconnect handler to be executed, so its okay to handle this by ourself.
|
||||
}
|
||||
|
||||
// connection established !
|
||||
//
|
||||
|
||||
// connection established !
|
||||
//
|
||||
if( evdp_outgoingconnection_established(fd, &s->evdp_data) == false ){
|
||||
return false; // we want the normal disconnect procedure.. with call to ondisconnect handler.
|
||||
}
|
||||
|
||||
|
||||
s->onSend = NULL;
|
||||
|
||||
ShowStatus("#%u connection successfull!\n", fd);
|
||||
|
||||
ShowStatus("#%u connection successfull!\n", fd);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}//end: _network_connect_establishedHandler()
|
||||
|
||||
|
||||
@ -515,7 +515,7 @@ int32 network_connect(bool v6,
|
||||
|
||||
// Originating IP/Port pair given ?
|
||||
if(from_addr != NULL && *from_addr != 0){
|
||||
//..
|
||||
//..
|
||||
#ifdef SO_REUSEADDR
|
||||
optval=1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
@ -526,7 +526,7 @@ int32 network_connect(bool v6,
|
||||
memset(&ip6, 0x00, sizeof(ip6));
|
||||
ip6.sin6_family = AF_INET6;
|
||||
ip6.sin6_port = htons(from_port);
|
||||
|
||||
|
||||
if(inet_pton(AF_INET6, from_addr, &ip6.sin6_addr) != 1){
|
||||
ShowError("network_connect(t, '%s', %u...): cannot parse originating (from) IPV6 address (errno: %u / %s)\n", addr, port, errno, strerror(errno));
|
||||
close(fd);
|
||||
@ -545,7 +545,7 @@ int32 network_connect(bool v6,
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Set non block
|
||||
@ -556,26 +556,26 @@ int32 network_connect(bool v6,
|
||||
}
|
||||
|
||||
|
||||
// Create ip addr block to connect to ..
|
||||
// Create ip addr block to connect to ..
|
||||
#ifdef ENABLE_IPV6
|
||||
if(v6 == true){
|
||||
memset(&ip6, 0x00, sizeof(ip6));
|
||||
ip6.sin6_family = AF_INET6;
|
||||
ip6.sin6_port = htons(port);
|
||||
|
||||
|
||||
if(inet_pton(AF_INET6, addr, &ip6.sin6_addr) != 1){
|
||||
ShowError("network_connect(t, '%s', %u...): cannot parse destination IPV6 address (errno: %u / %s)\n", addr, port, errno, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
#endif
|
||||
memset(&ip4, 0x00, sizeof(ip4));
|
||||
|
||||
|
||||
ip4.sin_family = AF_INET;
|
||||
ip4.sin_port = htons(port);
|
||||
ip4.sin_addr.s_addr = inet_addr(addr);
|
||||
ip4.sin_addr.s_addr = inet_addr(addr);
|
||||
#ifdef ENABLE_IPV6
|
||||
}
|
||||
#endif
|
||||
@ -594,17 +594,17 @@ int32 network_connect(bool v6,
|
||||
else
|
||||
#endif
|
||||
memcpy(&s->addr.v4, &ip4, sizeof(ip4));
|
||||
|
||||
|
||||
// Register @ EVDP. as outgoing (see doc of the function)
|
||||
if(evdp_addconnecting(fd, &s->evdp_data) == false){
|
||||
ShowError("network_connect(%c, '%s', %u...): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port);
|
||||
|
||||
// cleanup session x.x..
|
||||
|
||||
// cleanup session x.x..
|
||||
s->type = NST_FREE;
|
||||
s->onConnect = NULL;
|
||||
s->onDisconnect = NULL;
|
||||
s->onSend = NULL;
|
||||
|
||||
|
||||
// close, return error code.
|
||||
close(fd);
|
||||
return -1;
|
||||
@ -618,17 +618,17 @@ int32 network_connect(bool v6,
|
||||
ret = connect(fd, (struct sockaddr*)&ip4, sizeof(ip4));
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
if(ret != 0 && errno != EINPROGRESS){
|
||||
ShowWarning("network_connect(%c, '%s', %u...): connection failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno));
|
||||
|
||||
|
||||
// Cleanup session ..
|
||||
s->type = NST_FREE;
|
||||
s->onConnect = NULL;
|
||||
s->onDisconnect = NULL;
|
||||
s->onSend = NULL;
|
||||
|
||||
// .. remove from evdp and close fd.
|
||||
|
||||
// .. remove from evdp and close fd.
|
||||
evdp_remove(fd, &s->evdp_data);
|
||||
close(fd);
|
||||
return -1;
|
||||
@ -637,7 +637,7 @@ int32 network_connect(bool v6,
|
||||
// ! The Info Message :~D
|
||||
ShowStatus("network_connect fd#%u (%s:%u) in progress.. \n", fd, addr, port);
|
||||
|
||||
return fd;
|
||||
return fd;
|
||||
}//end: network_connect()
|
||||
|
||||
|
||||
@ -648,20 +648,20 @@ static bool _onSend(int32 fd){
|
||||
register int wLen;
|
||||
|
||||
if(s->type == NST_FREE)
|
||||
return true; // Possible due to multipl non coalsced event notifications
|
||||
// so onSend gets called after disconnect caused by an previous vent.
|
||||
// we can ignore the call to onSend, then.
|
||||
|
||||
return true; // Possible due to multipl non coalsced event notifications
|
||||
// so onSend gets called after disconnect caused by an previous vent.
|
||||
// we can ignore the call to onSend, then.
|
||||
|
||||
buf = s->write.buf;
|
||||
while(1){
|
||||
if(buf == NULL)
|
||||
break;
|
||||
|
||||
|
||||
buf_next = buf->next;
|
||||
|
||||
|
||||
|
||||
|
||||
szNeeded = (buf->dataLen - s->write.dataPos); // using th session-local .dataPos member, due to shared write buffer support.
|
||||
|
||||
|
||||
// try to write.
|
||||
wLen = write(fd, &buf->buf[s->write.dataPos], szNeeded);
|
||||
if(wLen == 0){
|
||||
@ -669,16 +669,16 @@ static bool _onSend(int32 fd){
|
||||
}else if(wLen == -1){
|
||||
if(errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return true; // dont disconnect / try again later.
|
||||
|
||||
// all other errors. .
|
||||
|
||||
// all other errors. .
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Wrote data.. =>
|
||||
szNeeded -= wLen;
|
||||
if(szNeeded > 0){
|
||||
// still data left ..
|
||||
//
|
||||
// still data left ..
|
||||
//
|
||||
s->write.dataPos += wLen; // fix offset.
|
||||
return true;
|
||||
}else{
|
||||
@ -686,29 +686,29 @@ static bool _onSend(int32 fd){
|
||||
// could be returned to pool.
|
||||
netbuffer_put(buf);
|
||||
s->write.n_outstanding--; // When threadsafe -> Interlocked here.
|
||||
s->write.dataPos = 0;
|
||||
s->write.dataPos = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
buf = buf_next;
|
||||
}
|
||||
|
||||
// okay,
|
||||
// reaching this part means:
|
||||
// while interrupted by break -
|
||||
// while interrupted by break -
|
||||
// which means all buffers are written, nothing left
|
||||
//
|
||||
|
||||
|
||||
s->write.buf_last = NULL;
|
||||
s->write.buf = NULL;
|
||||
s->write.n_outstanding = 0;
|
||||
s->write.dataPos = 0;
|
||||
|
||||
|
||||
// Remove from event dispatcher (write notification)
|
||||
//
|
||||
evdp_writable_remove(fd, &s->evdp_data);
|
||||
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}//end: _onSend()
|
||||
|
||||
|
||||
@ -717,13 +717,13 @@ static bool _onRORecv(int32 fd){
|
||||
register uint32 szNeeded;
|
||||
register char *p;
|
||||
register int rLen;
|
||||
|
||||
|
||||
if(s->type == NST_FREE)
|
||||
return true; // Possible due to multiple non coalesced events by evdp.
|
||||
// simply ignore this call returning positive result.
|
||||
|
||||
// simply ignore this call returning positive result.
|
||||
|
||||
// Initialize p and szNeeded depending on change
|
||||
//
|
||||
//
|
||||
switch(s->read.state){
|
||||
case NRS_WAITOP:
|
||||
szNeeded = s->read.head_left;
|
||||
@ -734,64 +734,64 @@ static bool _onRORecv(int32 fd){
|
||||
szNeeded = s->read.head_left;
|
||||
p = ((char*)&s->read.head[1]) + (2-szNeeded);
|
||||
break;
|
||||
|
||||
|
||||
case NRS_WAITDATA:{
|
||||
register netbuf buf = s->read.buf;
|
||||
|
||||
|
||||
szNeeded = (buf->dataLen - buf->dataPos);
|
||||
p = (char*)&buf->buf[ buf->dataPos ];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// .. the impossible gets possible ..
|
||||
break;
|
||||
|
||||
default:
|
||||
// .. the impossible gets possible ..
|
||||
ShowError("_onRORecv: fd #%u has unknown read.state (%d) - disconnecting\n", fd, s->read.state);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
rLen = read(fd, p, szNeeded);
|
||||
if(rLen == 0){
|
||||
// eof..
|
||||
return false;
|
||||
}else if(rLen == -1){
|
||||
|
||||
|
||||
if(errno == EAGAIN || errno == EWOULDBLOCK){
|
||||
// try again later .. (this case shouldnt happen, because we're event trigered.. but .. sometimes it happens :)
|
||||
return true;
|
||||
}
|
||||
|
||||
// an additional interesting case would be
|
||||
|
||||
// an additional interesting case would be
|
||||
// EINTR, this 'could' be handled .. but:
|
||||
// posix says that its possible that data gets currupted during irq
|
||||
// or data gor read and not reported.., so we'd have a data loss..
|
||||
// (which shouldnt happen with stream based protocols such as tcp)
|
||||
// its better to disonnect the client in that case.
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Got Data:
|
||||
// next action also depends on current state ..
|
||||
//
|
||||
// next action also depends on current state ..
|
||||
//
|
||||
szNeeded -= rLen;
|
||||
switch(s->read.state){
|
||||
case NRS_WAITOP:
|
||||
|
||||
if(szNeeded > 0){
|
||||
// still data missing ..
|
||||
// still data missing ..
|
||||
s->read.head_left = szNeeded;
|
||||
return true; // wait for completion.
|
||||
}else{
|
||||
// complete ..
|
||||
// complete ..
|
||||
// next state depends on packet type.
|
||||
|
||||
|
||||
s->read.head[1] = ((uint16*)s->netparser_data)[ s->read.head[0] ]; // store lenght of packet by opcode head[0] to head[1]
|
||||
|
||||
|
||||
if(s->read.head[1] == ROPACKET_UNKNOWN){
|
||||
// unknown packet - disconnect
|
||||
ShowWarning("_onRORecv: fd #%u got unlnown packet 0x%04x - disconnecting.\n", fd, s->read.head[0]);
|
||||
@ -804,74 +804,74 @@ static bool _onRORecv(int32 fd){
|
||||
s->read.head_left = 2;
|
||||
return true; //
|
||||
}
|
||||
else if(s->read.head[1] == 2){
|
||||
else if(s->read.head[1] == 2){
|
||||
// packet has no data (only opcode)
|
||||
register netbuf buf = netbuffer_get(2); // :D whoohoo its giant!
|
||||
|
||||
register netbuf buf = netbuffer_get(2); // :D whoohoo its giant!
|
||||
|
||||
NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
|
||||
buf->dataPos = 2;
|
||||
buf->dataLen = 2;
|
||||
buf->next = NULL;
|
||||
|
||||
|
||||
// Back to initial state -> Need opcode.
|
||||
s->read.state = NRS_WAITOP;
|
||||
s->read.head_left = 2;
|
||||
s->read.buf = NULL;
|
||||
|
||||
// Call completion routine here.
|
||||
s->onPacketComplete(fd, s->read.head[0], 2, buf);
|
||||
|
||||
|
||||
// Call completion routine here.
|
||||
s->onPacketComplete(fd, s->read.head[0], 2, buf);
|
||||
|
||||
return true; // done :)
|
||||
}
|
||||
else{
|
||||
// paket needs .. data ..
|
||||
register netbuf buf = netbuffer_get( s->read.head[1] );
|
||||
|
||||
|
||||
NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin.
|
||||
buf->dataPos = 2;
|
||||
buf->dataLen = s->read.head[1];
|
||||
buf->next = NULL;
|
||||
|
||||
|
||||
// attach buffer.
|
||||
s->read.buf = buf;
|
||||
|
||||
|
||||
// set state:
|
||||
s->read.state = NRS_WAITDATA;
|
||||
|
||||
s->read.state = NRS_WAITDATA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}//endif: szNeeded > 0 (opcode read completed?)
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case NRS_WAITLEN:
|
||||
|
||||
|
||||
if(szNeeded > 0){
|
||||
// incomplete ..
|
||||
// incomplete ..
|
||||
s->read.head_left = szNeeded;
|
||||
return true;
|
||||
}else{
|
||||
|
||||
|
||||
if(s->read.head[1] == 4){
|
||||
// packet has no data (only opcode + length)
|
||||
register netbuf buf = netbuffer_get( 4 );
|
||||
|
||||
NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
|
||||
|
||||
NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
|
||||
buf->dataPos = 4;
|
||||
buf->dataLen = 4;
|
||||
buf->next = NULL;
|
||||
|
||||
|
||||
// set initial state (need opcode)
|
||||
s->read.state = NRS_WAITOP;
|
||||
s->read.head_left = 2;
|
||||
s->read.head_left = 2;
|
||||
s->read.buf = NULL;
|
||||
|
||||
|
||||
// call completion routine.
|
||||
s->onPacketComplete(fd, s->read.head[0], 4, buf);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else if(s->read.head[1] < 4){
|
||||
// invalid header.
|
||||
@ -882,64 +882,64 @@ static bool _onRORecv(int32 fd){
|
||||
// Data needed
|
||||
// next state -> waitdata!
|
||||
register netbuf buf = netbuffer_get( s->read.head[1] );
|
||||
|
||||
|
||||
NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL
|
||||
buf->dataPos = 4;
|
||||
buf->dataLen = s->read.head[1];
|
||||
buf->next = NULL;
|
||||
|
||||
|
||||
// attach to session:
|
||||
s->read.buf = buf;
|
||||
s->read.state = NRS_WAITDATA;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}//endif: szNeeded > 0 (length read complete?)
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case NRS_WAITDATA:
|
||||
|
||||
if(szNeeded == 0){
|
||||
// Packet finished!
|
||||
// compltion.
|
||||
register netbuf buf = s->read.buf;
|
||||
|
||||
|
||||
// set initial state.
|
||||
s->read.state = NRS_WAITOP;
|
||||
s->read.head_left = 2;
|
||||
s->read.buf = NULL;
|
||||
|
||||
|
||||
// Call completion routine.
|
||||
s->onPacketComplete(fd, NBUFW(buf, 0), buf->dataLen, buf);
|
||||
|
||||
|
||||
return true;
|
||||
}else{
|
||||
// still data needed
|
||||
s->read.buf->dataPos += rLen;
|
||||
|
||||
return true;
|
||||
// still data needed
|
||||
s->read.buf->dataPos += rLen;
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
default:
|
||||
ShowError("_onRORecv: fd #%u has unknown read.state (%d) [2] - disconnecting\n", fd, s->read.state);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}//end: _onRORecv()
|
||||
|
||||
|
||||
void network_send(int32 fd, netbuf buf){
|
||||
register SESSION *s = &g_Session[fd];
|
||||
|
||||
|
||||
#ifdef PARANOID_CHECKS
|
||||
if(fd >= MAXCONN){
|
||||
ShowError("network_send: tried to attach buffer to connection idientifer #%u which is out of bounds.\n", fd);
|
||||
@ -951,84 +951,84 @@ void network_send(int32 fd, netbuf buf){
|
||||
|
||||
if(s->type == NST_FREE)
|
||||
return;
|
||||
|
||||
|
||||
// Check Max Outstanding buffers limit.
|
||||
if( (s->write.max_outstanding > 0) &&
|
||||
(s->write.n_outstanding >= s->write.max_outstanding) ){
|
||||
|
||||
|
||||
ShowWarning("network_send: fd #%u max Outstanding buffers exceeded. - disconnecting.\n", fd);
|
||||
network_disconnect(fd);
|
||||
//
|
||||
_network_free_netbuf_async(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Attach to the end:
|
||||
buf->next = NULL;
|
||||
if(s->write.buf_last != NULL){
|
||||
s->write.buf_last->next = buf;
|
||||
s->write.buf_last->next = buf;
|
||||
s->write.buf_last = buf;
|
||||
|
||||
}else{
|
||||
// currently no buffer attached.
|
||||
s->write.buf = s->write.buf_last = buf;
|
||||
|
||||
|
||||
// register @ evdp for writable notification.
|
||||
evdp_writable_add(fd, &s->evdp_data); //
|
||||
evdp_writable_add(fd, &s->evdp_data); //
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
s->write.n_outstanding++;
|
||||
|
||||
|
||||
}//end: network_send()
|
||||
|
||||
|
||||
void network_parser_set_ro(int32 fd,
|
||||
int16 *packetlentable,
|
||||
void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
|
||||
void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
|
||||
){
|
||||
register SESSION *s = &g_Session[fd];
|
||||
register netbuf b, nb; // used for potential free attached buffers.
|
||||
|
||||
|
||||
if(s->type == NST_FREE)
|
||||
return;
|
||||
|
||||
|
||||
s->onPacketComplete = onPacketCompleteProc;
|
||||
|
||||
|
||||
s->onRecv = _onRORecv; // ..
|
||||
s->onSend = _onSend; // Using the normal generic netbuf based send function.
|
||||
|
||||
|
||||
s->netparser_data = packetlentable;
|
||||
|
||||
|
||||
// Initial State -> Need Packet OPCode.
|
||||
s->read.state = NRS_WAITOP;
|
||||
s->read.head_left = 2;
|
||||
s->read.head_left = 2;
|
||||
|
||||
|
||||
|
||||
// Detach (if..) all buffers.
|
||||
if(s->read.buf != NULL){
|
||||
_network_free_netbuf_async(s->read.buf); //
|
||||
s->read.buf = NULL;
|
||||
s->read.buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
if(s->write.buf != NULL){
|
||||
b = s->write.buf;
|
||||
while(1){
|
||||
nb = b->next;
|
||||
|
||||
|
||||
_network_free_netbuf_async(b);
|
||||
|
||||
|
||||
b = nb;
|
||||
}
|
||||
|
||||
|
||||
s->write.buf = NULL;
|
||||
s->write.buf_last = NULL;
|
||||
s->write.n_outstanding = 0;
|
||||
}
|
||||
|
||||
|
||||
// not changing any limits on outstanding ..
|
||||
//
|
||||
|
||||
|
||||
}//end: network_parser_set_ro()
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include "cbasetypes.h"
|
||||
#include "netbuffer.h"
|
||||
#include "netbuffer.h"
|
||||
#include "evdp.h"
|
||||
|
||||
#ifndef MAXCONN
|
||||
@ -14,19 +14,19 @@
|
||||
typedef struct SESSION{
|
||||
EVDP_DATA evdp_data; // Must be always the frist member! (some evdp's may rely on this fact)
|
||||
|
||||
// Connection Type
|
||||
// Connection Type
|
||||
enum{ NST_FREE=0, NST_LISTENER = 1, NST_CLIENT=2, NST_OUTGOING=3} type;
|
||||
|
||||
// Flags / Settings.
|
||||
bool v6; // is v6?
|
||||
bool disconnect_in_progress; // To prevent stack overflows / recursive calls.
|
||||
|
||||
|
||||
|
||||
|
||||
union{ // union to save memory.
|
||||
struct sockaddr_in v4;
|
||||
struct sockaddr_in6 v6;
|
||||
}addr;
|
||||
|
||||
|
||||
|
||||
// "lowlevel" Handlers
|
||||
// (Implemented by the protocol specific parser)
|
||||
@ -34,9 +34,9 @@ typedef struct SESSION{
|
||||
bool (*onRecv)(int32 fd); // return false = disconnect
|
||||
bool (*onSend)(int32 fd); // return false = disconnect
|
||||
|
||||
// Event Handlers for LISTENER type sockets
|
||||
// Event Handlers for LISTENER type sockets
|
||||
//
|
||||
// onConnect gets Called when a connection has been
|
||||
// onConnect gets Called when a connection has been
|
||||
// successfully accepted.
|
||||
// Session entry is available in this Handler!
|
||||
// A returncode of false will reejct the connection (disconnect)
|
||||
@ -44,46 +44,46 @@ typedef struct SESSION{
|
||||
// The onDisconnect handler wont get called!
|
||||
// Note: the onConnect Handler is also responsible for setting
|
||||
// the appropriate netparser (which implements onRecv/onSend..) [protocol specific]
|
||||
//
|
||||
// onDisconnect gets called when a connection gets disconnected
|
||||
//
|
||||
// onDisconnect gets called when a connection gets disconnected
|
||||
// (by peer as well as by core)
|
||||
//
|
||||
bool (*onConnect)(int32 fd); // return false = disconnect (wont accept)
|
||||
void (*onDisconnect)(int32 fd);
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Parser specific data
|
||||
//
|
||||
void *netparser_data; // incase of RO Packet Parser, pointer to packet len table (uint16array)
|
||||
void (*onPacketComplete)(int32 fd, uint16 op, uint16 len, netbuf buf);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Buffers
|
||||
//
|
||||
//
|
||||
struct{
|
||||
enum NETREADSTATE { NRS_WAITOP = 0, NRS_WAITLEN = 1, NRS_WAITDATA = 2} state;
|
||||
|
||||
|
||||
uint32 head_left;
|
||||
uint16 head[2];
|
||||
|
||||
|
||||
netbuf buf;
|
||||
} read;
|
||||
|
||||
struct{
|
||||
uint32 max_outstanding;
|
||||
uint32 n_outstanding;
|
||||
|
||||
|
||||
uint32 dataPos;
|
||||
|
||||
netbuf buf, buf_last;
|
||||
|
||||
netbuf buf, buf_last;
|
||||
} write;
|
||||
|
||||
|
||||
// Application Level data Pointer
|
||||
// (required for backward compatibility with previous athena socket system.)
|
||||
void *data;
|
||||
|
||||
|
||||
} SESSION;
|
||||
|
||||
|
||||
@ -101,10 +101,10 @@ void network_final();
|
||||
void network_do();
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Adds a new listner.
|
||||
*
|
||||
* @param v6 v6 listner?
|
||||
* @param v6 v6 listner?
|
||||
* @param *addr the address to listen on.
|
||||
* @param port port to listen on
|
||||
*
|
||||
@ -135,7 +135,7 @@ int32 network_connect(bool v6,
|
||||
void (*onConnectionLooseHandler)(int32 fd)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects the given connection
|
||||
@ -143,14 +143,14 @@ int32 network_connect(bool v6,
|
||||
* @param fd connection identifier.
|
||||
*
|
||||
* @Note:
|
||||
* - onDisconnect callback gets called!
|
||||
* - onDisconnect callback gets called!
|
||||
* - cleares (returns) all assigned buffers
|
||||
*
|
||||
*/
|
||||
void network_disconnect(int32 fd);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Attach's a netbuffer at the end of sending queue to the given connection
|
||||
*
|
||||
* @param fd connection identifier
|
||||
@ -161,7 +161,7 @@ void network_send(int32 fd, netbuf buf);
|
||||
|
||||
/**
|
||||
* Sets the parser to RO Protocol like Packet Parser.
|
||||
*
|
||||
*
|
||||
* @param fd connection identifier
|
||||
* @param *packetlentable pointer to array of uint16 in size of UINT16_MAX,
|
||||
* @param onComplteProc callback for packet completion.
|
||||
@ -178,7 +178,7 @@ void network_send(int32 fd, netbuf buf);
|
||||
*/
|
||||
void network_parser_set_ro(int32 fd,
|
||||
int16 *packetlentable,
|
||||
void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
|
||||
void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf)
|
||||
);
|
||||
#define ROPACKET_UNKNOWN UINT16_MAX
|
||||
#define ROPACKET_DYNLEN 0
|
||||
|
||||
@ -17,10 +17,10 @@ int nullpo_chk_f(const char *file, int line, const char *func, const void *targe
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
||||
if (target != NULL)
|
||||
return 0;
|
||||
|
||||
|
||||
va_start(ap, fmt);
|
||||
nullpo_info_core(file, line, func, fmt, ap);
|
||||
va_end(ap);
|
||||
@ -39,11 +39,11 @@ int nullpo_chk(const char *file, int line, const char *func, const void *target)
|
||||
/*======================================
|
||||
* nullpo Information output (external call)
|
||||
*--------------------------------------*/
|
||||
void nullpo_info_f(const char *file, int line, const char *func,
|
||||
void nullpo_info_f(const char *file, int line, const char *func,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
||||
va_start(ap, fmt);
|
||||
nullpo_info_core(file, line, func, fmt, ap);
|
||||
va_end(ap);
|
||||
@ -57,12 +57,12 @@ void nullpo_info(const char *file, int line, const char *func)
|
||||
static void nullpo_info_core_(const char *file, int line, const char *func){
|
||||
if (file == NULL)
|
||||
file = "??";
|
||||
|
||||
|
||||
func =
|
||||
func == NULL ? "unknown":
|
||||
func[0] == '\0' ? "unknown":
|
||||
func;
|
||||
|
||||
|
||||
ShowMessage("--- nullpo info --------------------------------------------\n");
|
||||
ShowMessage("%s:%d: in func `%s'\n", file, line, func);
|
||||
}
|
||||
@ -70,7 +70,7 @@ static void nullpo_info_core_(const char *file, int line, const char *func){
|
||||
/*======================================
|
||||
* nullpo intelligence Output (Main)
|
||||
*--------------------------------------*/
|
||||
static void nullpo_info_core(const char *file, int line, const char *func,
|
||||
static void nullpo_info_core(const char *file, int line, const char *func,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
nullpo_info_core_(file,line,func);
|
||||
@ -79,7 +79,7 @@ static void nullpo_info_core(const char *file, int line, const char *func,
|
||||
if (fmt[0] != '\0')
|
||||
{
|
||||
vprintf(fmt, ap);
|
||||
|
||||
|
||||
// Check whether the new line at the end
|
||||
if (fmt[strlen(fmt)-1] != '\n')
|
||||
ShowMessage("\n");
|
||||
|
||||
@ -217,7 +217,7 @@ void nullpo_info(const char *file, int line, const char *func);
|
||||
* 備考や関係変数の書き出しなどに
|
||||
*--------------------------------------
|
||||
*/
|
||||
void nullpo_info_f(const char *file, int line, const char *func,
|
||||
void nullpo_info_f(const char *file, int line, const char *func,
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf,4,5)));
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//
|
||||
//
|
||||
// Athena style config parser
|
||||
// (would be better to have "one" implementation instead of .. 4 :)
|
||||
//
|
||||
// (would be better to have "one" implementation instead of .. 4 :)
|
||||
//
|
||||
//
|
||||
// Author: Florian Wilkemeyer <fw@f-ws.de>
|
||||
//
|
||||
@ -33,7 +33,7 @@ struct conf_value{
|
||||
int64 intval;
|
||||
bool bval;
|
||||
double floatval;
|
||||
size_t strval_len; // not includung \0
|
||||
size_t strval_len; // not includung \0
|
||||
char strval[16];
|
||||
};
|
||||
|
||||
@ -42,22 +42,22 @@ struct conf_value{
|
||||
static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
|
||||
struct conf_value *v;
|
||||
/* size_t sz;
|
||||
|
||||
|
||||
sz = sizeof(struct conf_value);
|
||||
if(val_len >= sizeof(v->strval))
|
||||
sz += (val_len - sizeof(v->strval) + 1);*/
|
||||
|
||||
|
||||
v = (struct conf_value*)aCalloc(1, sizeof(struct conf_value));
|
||||
if(v == NULL){
|
||||
ShowFatalError("raconf: makeValue => Out of Memory while allocating new node.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
memcpy(v->strval, val, val_len);
|
||||
v->strval[val_len+1] = '\0';
|
||||
v->strval_len = val_len;
|
||||
|
||||
|
||||
|
||||
|
||||
// Parse boolean value:
|
||||
if((val_len == 4) && (strncmpi("true", val, 4) == 0))
|
||||
v->bval = true;
|
||||
@ -80,13 +80,13 @@ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
|
||||
else if((val_len == 4) && (strncmpi("nein", val, 4) == 0))
|
||||
v->bval = false;
|
||||
else if((val_len == 1) && (*val == '0'))
|
||||
v->bval = false;
|
||||
v->bval = false;
|
||||
else
|
||||
v->bval = false; // assume false.
|
||||
|
||||
|
||||
// Parse number
|
||||
// Supported formats:
|
||||
// prefix: 0x hex .
|
||||
// prefix: 0x hex .
|
||||
// postix: h for hex
|
||||
// b for bin (dual)
|
||||
if( (val_len >= 1 && (val[val_len] == 'h')) || (val_len >= 2 && (val[0] == '0' && val[1] == 'x')) ){//HEX!
|
||||
@ -104,7 +104,7 @@ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
|
||||
// is it float?
|
||||
bool is_float = false;
|
||||
char *p;
|
||||
|
||||
|
||||
for(p = val; *p != '\0'; p++){
|
||||
if(*p == '.'){
|
||||
v->floatval = strtod(val, NULL);
|
||||
@ -113,7 +113,7 @@ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(is_float == false){
|
||||
v->intval = strtoull(val, NULL, 10);
|
||||
v->floatval = (double) v->intval;
|
||||
@ -125,8 +125,8 @@ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){
|
||||
else
|
||||
v->intval = 0;
|
||||
}
|
||||
|
||||
return v;
|
||||
|
||||
return v;
|
||||
}//end: makeValue()
|
||||
|
||||
|
||||
@ -139,38 +139,38 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
int linecnt;
|
||||
size_t linelen;
|
||||
size_t currentSection_len;
|
||||
|
||||
|
||||
fp = fopen(fileName, "r");
|
||||
if(fp == NULL){
|
||||
ShowError("configParse: cannot open '%s' for reading.\n", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Start with empty section:
|
||||
currentSection[0] = '\0';
|
||||
currentSection_len = 0;
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
linecnt = 0;
|
||||
while(1){
|
||||
linecnt++;
|
||||
|
||||
|
||||
if(fgets(line, sizeof(line), fp) != line)
|
||||
break;
|
||||
|
||||
linelen = strlen(line);
|
||||
p = line;
|
||||
|
||||
|
||||
// Skip whitespaces from beginning (space and tab)
|
||||
_line_begin_skip_whities:
|
||||
c = *p;
|
||||
if(c == ' ' || c == '\t'){
|
||||
p++;
|
||||
p++;
|
||||
linelen--;
|
||||
goto _line_begin_skip_whities;
|
||||
}
|
||||
|
||||
|
||||
// Remove linebreaks as (cr or lf) and whitespaces from line end!
|
||||
_line_end_skip_whities_and_breaks:
|
||||
c = p[linelen-1];
|
||||
@ -178,29 +178,29 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
p[--linelen] = '\0';
|
||||
goto _line_end_skip_whities_and_breaks;
|
||||
}
|
||||
|
||||
// Empty line?
|
||||
|
||||
// Empty line?
|
||||
// or line starts with comment (commented out)?
|
||||
if(linelen == 0 || (p[0] == '/' && p[1] == '/') || p[0] == ';')
|
||||
continue;
|
||||
|
||||
|
||||
// Variable names can contain:
|
||||
// A-Za-z-_.0-9
|
||||
//
|
||||
// Sections start with [ .. ] (INI Style)
|
||||
//
|
||||
c = *p;
|
||||
|
||||
|
||||
// check what we have.. :)
|
||||
if(c == '['){ // got section!
|
||||
// Got Section!
|
||||
// Search for ]
|
||||
// Search for ]
|
||||
char *start = (p+1);
|
||||
|
||||
|
||||
while(1){
|
||||
++p;
|
||||
c = *p;
|
||||
|
||||
|
||||
if(c == '\0'){
|
||||
ShowError("Syntax Error: unterminated Section name in %s:%u (expected ']')\n", fileName, linecnt);
|
||||
fclose(fp);
|
||||
@ -211,14 +211,14 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Set section!
|
||||
*p = '\0'; // add termination here.
|
||||
memcpy(currentSection, start, (p-start)+1 ); // we'll copy \0, too! (we replaced the ] backet with \0.)
|
||||
currentSection_len = (p-start);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
}else if( (c >= '0' && c <= '9') || (c == '-') || (c == ' ') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
|
||||
// skip .. (allowed char / specifier)
|
||||
continue;
|
||||
@ -227,43 +227,43 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
}//endwhile: parse section name
|
||||
|
||||
|
||||
|
||||
}//endwhile: parse section name
|
||||
|
||||
|
||||
}else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
|
||||
// Got variable!
|
||||
// Search for '=' or ':' wich termiantes the name
|
||||
// Got variable!
|
||||
// Search for '=' or ':' wich termiantes the name
|
||||
char *start = p;
|
||||
char *valuestart = NULL;
|
||||
size_t start_len;
|
||||
|
||||
|
||||
while(1){
|
||||
++p;
|
||||
c = *p;
|
||||
|
||||
|
||||
if(c == '\0'){
|
||||
ShowError("Syntax Error: unterminated Variable name in %s:%u\n", fileName, linecnt);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}else if( (c == '=') || (c == ':') ){
|
||||
// got name termination
|
||||
|
||||
|
||||
*p = '\0'; // Terminate it so (start) will hold the pointer to the name.
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
}else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){
|
||||
// skip .. allowed char
|
||||
// skip .. allowed char
|
||||
continue;
|
||||
}else{
|
||||
ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Variable name.\n", c, fileName, linecnt, (p-line));
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
}//endwhile: parse var name
|
||||
|
||||
|
||||
}//endwhile: parse var name
|
||||
|
||||
start_len = (p-start);
|
||||
if(start_len >= VARNAME_LEN){
|
||||
ShowError("%s:%u Variable length exceeds limit of %u Characters.\n", fileName, linecnt, VARNAME_LEN-1);
|
||||
@ -274,20 +274,20 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
valuestart = (p+1);
|
||||
|
||||
|
||||
|
||||
|
||||
valuestart = (p+1);
|
||||
|
||||
|
||||
// Skip whitespace from begin of value (tab and space)
|
||||
_skip_value_begin_whities:
|
||||
c = *valuestart;
|
||||
c = *valuestart;
|
||||
if(c == ' ' || c == '\t'){
|
||||
valuestart++;
|
||||
goto _skip_value_begin_whities;
|
||||
}
|
||||
|
||||
// Scan for value termination,
|
||||
|
||||
// Scan for value termination,
|
||||
// wich can be \0 or comment start (// or ; (INI) )
|
||||
//
|
||||
p = valuestart;
|
||||
@ -305,15 +305,15 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
p++;
|
||||
}//endwhile: search var value end.
|
||||
|
||||
|
||||
|
||||
|
||||
// Strip whitespaces from end of value.
|
||||
if(valuestart != p){ // not empty!
|
||||
p--;
|
||||
_strip_value_end_whities:
|
||||
_strip_value_end_whities:
|
||||
c = *p;
|
||||
if(c == ' ' || c == '\t'){
|
||||
*p = '\0';
|
||||
@ -321,9 +321,9 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
goto _strip_value_end_whities;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Buildin Hook:
|
||||
if( stricmp(start, "import") == 0){
|
||||
if( configParse(inst, valuestart) != true){
|
||||
@ -334,7 +334,7 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
struct conf_value *v, *o;
|
||||
char key[ (SECTION_LEN+VARNAME_LEN+1+1) ]; //+1 for delimiter, +1 for termination.
|
||||
size_t section_len;
|
||||
|
||||
|
||||
if(*currentSection == '\0'){ // empty / none
|
||||
strncpy(key, "<unnamed>",9);
|
||||
section_len = 9;
|
||||
@ -342,39 +342,39 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
strncpy(key, currentSection, currentSection_len);
|
||||
section_len = currentSection_len;
|
||||
}
|
||||
|
||||
key[section_len] = '.'; // Delim
|
||||
|
||||
strncpy(&key[section_len+1], start, start_len);
|
||||
|
||||
key[section_len + start_len + 1] = '\0';
|
||||
|
||||
|
||||
v = makeValue(key, valuestart, (p-valuestart) );
|
||||
|
||||
key[section_len] = '.'; // Delim
|
||||
|
||||
strncpy(&key[section_len+1], start, start_len);
|
||||
|
||||
key[section_len + start_len + 1] = '\0';
|
||||
|
||||
|
||||
v = makeValue(key, valuestart, (p-valuestart) );
|
||||
|
||||
// Try to get the old one before
|
||||
o = strdb_get(inst->db, key);
|
||||
if(o != NULL){
|
||||
strdb_remove(inst->db, key);
|
||||
aFree(o); //
|
||||
aFree(o); //
|
||||
}
|
||||
|
||||
|
||||
strdb_put( inst->db, key, v);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
ShowError("Syntax Error: unexpected Character '%c' in %s:%u (offset %u)\n", c, fileName, linecnt, (p-line) );
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}//end: configParse()
|
||||
@ -395,24 +395,24 @@ static bool configParse(raconf inst, const char *fileName){
|
||||
strncpy(&dest[section_len+1], key, key_len); \
|
||||
dest[section_len + key_len + 1] = '\0'; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
raconf raconf_parse(const char *file_name){
|
||||
struct raconf *rc;
|
||||
|
||||
|
||||
rc = aCalloc(1, sizeof(struct raconf) );
|
||||
if(rc == NULL){
|
||||
ShowFatalError("raconf_parse: failed to allocate memory for new handle\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc->db = strdb_alloc(DB_OPT_BASE | DB_OPT_DUP_KEY, 98);
|
||||
rc->db = strdb_alloc(DB_OPT_BASE | DB_OPT_DUP_KEY, 98);
|
||||
//
|
||||
|
||||
|
||||
if(configParse(rc, file_name) != true){
|
||||
ShowError("Failed to Parse Configuration file '%s'\n", file_name);
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}//end: raconf_parse()
|
||||
|
||||
@ -420,7 +420,7 @@ raconf raconf_parse(const char *file_name){
|
||||
void raconf_destroy(raconf rc){
|
||||
DBIterator *iter;
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
// Clear all entrys in db.
|
||||
iter = db_iterator(rc->db);
|
||||
for( v = (struct conf_value*)dbi_first(iter); dbi_exists(iter); v = (struct conf_value*)dbi_next(iter) ){
|
||||
@ -429,15 +429,15 @@ void raconf_destroy(raconf rc){
|
||||
dbi_destroy(iter);
|
||||
|
||||
db_destroy(rc->db);
|
||||
|
||||
aFree(rc);
|
||||
|
||||
|
||||
aFree(rc);
|
||||
|
||||
}//end: raconf_destroy()
|
||||
|
||||
bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
|
||||
v = strdb_get(rc->db, keystr);
|
||||
@ -451,7 +451,7 @@ bool raconf_getbool(raconf rc, const char *section, const char *key, bool _defa
|
||||
float raconf_getfloat(raconf rc,const char *section, const char *key, float _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
|
||||
v = strdb_get(rc->db, keystr);
|
||||
@ -465,9 +465,9 @@ float raconf_getfloat(raconf rc,const char *section, const char *key, float _def
|
||||
int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
|
||||
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL)
|
||||
return _default;
|
||||
@ -481,7 +481,7 @@ const char* raconf_getstr(raconf rc, const char *section, const char *key, cons
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
MAKEKEY(keystr, section, key);
|
||||
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL)
|
||||
@ -494,11 +494,11 @@ const char* raconf_getstr(raconf rc, const char *section, const char *key, cons
|
||||
bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
|
||||
|
||||
MAKEKEY(keystr, fallback_section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
@ -506,7 +506,7 @@ bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_secti
|
||||
}else{
|
||||
return v->bval;
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return v->bval;
|
||||
}
|
||||
@ -516,11 +516,11 @@ bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_secti
|
||||
float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
|
||||
|
||||
MAKEKEY(keystr, fallback_section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
@ -528,22 +528,22 @@ float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_sect
|
||||
}else{
|
||||
return (float)v->floatval;
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return (float)v->floatval;
|
||||
}
|
||||
|
||||
|
||||
}//end: raconf_getfloatEx()
|
||||
|
||||
|
||||
int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
|
||||
|
||||
MAKEKEY(keystr, fallback_section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
@ -551,7 +551,7 @@ int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_sect
|
||||
}else{
|
||||
return v->intval;
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return v->intval;
|
||||
}
|
||||
@ -562,11 +562,11 @@ int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_sect
|
||||
const char* raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default){
|
||||
char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1];
|
||||
struct conf_value *v;
|
||||
|
||||
|
||||
MAKEKEY(keystr, section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
|
||||
|
||||
MAKEKEY(keystr, fallback_section, key);
|
||||
v = strdb_get(rc->db, keystr);
|
||||
if(v == NULL){
|
||||
@ -574,7 +574,7 @@ const char* raconf_getstrEx(raconf rc, const char *section, const char *fallbac
|
||||
}else{
|
||||
return v->strval;
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return v->strval;
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
#include "cbasetypes.h"
|
||||
|
||||
// rAthena generic configuration file parser
|
||||
//
|
||||
// Config file Syntax is athena style
|
||||
//
|
||||
// Config file Syntax is athena style
|
||||
// extended with ini style support (including sections)
|
||||
//
|
||||
// Comments are started with // or ; (ini style)
|
||||
@ -17,9 +17,9 @@
|
||||
typedef struct raconf *raconf;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Parses a rAthna Configuration file
|
||||
*
|
||||
*
|
||||
* @param file_name path to the file to parse
|
||||
*
|
||||
* @returns not NULL incase of success
|
||||
@ -27,7 +27,7 @@ typedef struct raconf *raconf;
|
||||
raconf raconf_parse(const char *file_name);
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Frees a Handle received from raconf_parse
|
||||
*
|
||||
* @param rc - the handle to free
|
||||
@ -35,17 +35,17 @@ raconf raconf_parse(const char *file_name);
|
||||
void raconf_destroy(raconf rc);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value for Section / Key pair, if key not exists returns _default!
|
||||
/**
|
||||
* Gets the value for Section / Key pair, if key not exists returns _default!
|
||||
*
|
||||
*/
|
||||
bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default);
|
||||
float raconf_getfloat(raconf rc,const char *section, const char *key, float _default);
|
||||
int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default);
|
||||
int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default);
|
||||
const char* raconf_getstr(raconf rc, const char *section, const char *key, const char *_default);
|
||||
|
||||
/**
|
||||
* Gets the value for Section / Key pair, but has fallback section option if not found in section,
|
||||
* Gets the value for Section / Key pair, but has fallback section option if not found in section,
|
||||
* if not found in both - default gets returned.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -99,7 +99,7 @@ char console_log_filepath[32] = "./log/unknown.log";
|
||||
// ansi compatible printf with control sequence parser for windows
|
||||
// fast hack, handle with care, not everything implemented
|
||||
//
|
||||
// \033[#;...;#m - Set Graphics Rendition (SGR)
|
||||
// \033[#;...;#m - Set Graphics Rendition (SGR)
|
||||
//
|
||||
// printf("\x1b[1;31;40m"); // Bright red on black
|
||||
// printf("\x1b[3;33;45m"); // Blinking yellow on magenta (blink not implemented)
|
||||
@ -118,19 +118,19 @@ char console_log_filepath[32] = "./log/unknown.log";
|
||||
// 8 - Concealed (invisible)
|
||||
//
|
||||
// \033[#A - Cursor Up (CUU)
|
||||
// Moves the cursor up by the specified number of lines without changing columns.
|
||||
// Moves the cursor up by the specified number of lines without changing columns.
|
||||
// If the cursor is already on the top line, this sequence is ignored. \e[A is equivalent to \e[1A.
|
||||
//
|
||||
// \033[#B - Cursor Down (CUD)
|
||||
// Moves the cursor down by the specified number of lines without changing columns.
|
||||
// Moves the cursor down by the specified number of lines without changing columns.
|
||||
// If the cursor is already on the bottom line, this sequence is ignored. \e[B is equivalent to \e[1B.
|
||||
//
|
||||
// \033[#C - Cursor Forward (CUF)
|
||||
// Moves the cursor forward by the specified number of columns without changing lines.
|
||||
// Moves the cursor forward by the specified number of columns without changing lines.
|
||||
// If the cursor is already in the rightmost column, this sequence is ignored. \e[C is equivalent to \e[1C.
|
||||
//
|
||||
// \033[#D - Cursor Backward (CUB)
|
||||
// Moves the cursor back by the specified number of columns without changing lines.
|
||||
// Moves the cursor back by the specified number of columns without changing lines.
|
||||
// If the cursor is already in the leftmost column, this sequence is ignored. \e[D is equivalent to \e[1D.
|
||||
//
|
||||
// \033[#E - Cursor Next Line (CNL)
|
||||
@ -143,15 +143,15 @@ char console_log_filepath[32] = "./log/unknown.log";
|
||||
// Moves the cursor to indicated column in current row. \e[G is equivalent to \e[1G.
|
||||
//
|
||||
// \033[#;#H - Cursor Position (CUP)
|
||||
// Moves the cursor to the specified position. The first # specifies the line number,
|
||||
// the second # specifies the column. If you do not specify a position, the cursor moves to the home position:
|
||||
// Moves the cursor to the specified position. The first # specifies the line number,
|
||||
// the second # specifies the column. If you do not specify a position, the cursor moves to the home position:
|
||||
// the upper-left corner of the screen (line 1, column 1).
|
||||
//
|
||||
// \033[#;#f - Horizontal & Vertical Position
|
||||
// (same as \033[#;#H)
|
||||
//
|
||||
// \033[s - Save Cursor Position (SCP)
|
||||
// The current cursor position is saved.
|
||||
// The current cursor position is saved.
|
||||
//
|
||||
// \033[u - Restore cursor position (RCP)
|
||||
// Restores the cursor position saved with the (SCP) sequence \033[s.
|
||||
@ -221,7 +221,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
|
||||
WriteFile(handle, p, (DWORD)(q-p), &written, 0);
|
||||
|
||||
if( q[1]!='[' )
|
||||
{ // write the escape char (whatever purpose it has)
|
||||
{ // write the escape char (whatever purpose it has)
|
||||
if(0==WriteConsole(handle, q, 1, &written, 0) )
|
||||
WriteFile(handle,q, 1, &written, 0);
|
||||
p=q+1; //and start searching again
|
||||
@ -241,7 +241,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
|
||||
q=q+2;
|
||||
for(;;)
|
||||
{
|
||||
if( ISDIGIT(*q) )
|
||||
if( ISDIGIT(*q) )
|
||||
{ // add number to number array, only accept 2digits, shift out the rest
|
||||
// so // \033[123456789m will become \033[89m
|
||||
numbers[numpoint] = (numbers[numpoint]<<4) | (*q-'0');
|
||||
@ -358,12 +358,12 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
|
||||
else if(num==2)
|
||||
{ // Number of chars on screen.
|
||||
cnt = info.dwSize.X * info.dwSize.Y;
|
||||
SetConsoleCursorPosition(handle, origin);
|
||||
SetConsoleCursorPosition(handle, origin);
|
||||
}
|
||||
else// 0 and default
|
||||
{ // number of chars from cursor to end
|
||||
origin = info.dwCursorPosition;
|
||||
cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X;
|
||||
cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X;
|
||||
}
|
||||
FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp);
|
||||
FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp);
|
||||
@ -397,7 +397,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
|
||||
else if( *q == 'H' || *q == 'f' )
|
||||
{ // \033[#;#H - Cursor Position (CUP)
|
||||
// \033[#;#f - Horizontal & Vertical Position
|
||||
// The first # specifies the line number, the second # specifies the column.
|
||||
// The first # specifies the line number, the second # specifies the column.
|
||||
// The default for both is 1
|
||||
info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0;
|
||||
info.dwCursorPosition.Y = (numpoint && numbers[numpoint-1])?(numbers[numpoint-1]>>4)*10+((numbers[numpoint-1]&0x0F)-1):0;
|
||||
@ -494,7 +494,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr)
|
||||
--q;
|
||||
}
|
||||
// skip the sequencer and search again
|
||||
p = q+1;
|
||||
p = q+1;
|
||||
break;
|
||||
}// end while
|
||||
}
|
||||
@ -550,7 +550,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
|
||||
{ // find the escape character
|
||||
fprintf(file, "%.*s", (int)(q-p), p); // write up to the escape
|
||||
if( q[1]!='[' )
|
||||
{ // write the escape char (whatever purpose it has)
|
||||
{ // write the escape char (whatever purpose it has)
|
||||
fprintf(file, "%.*s", 1, q);
|
||||
p=q+1; //and start searching again
|
||||
}
|
||||
@ -563,7 +563,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
|
||||
q=q+2;
|
||||
while(1)
|
||||
{
|
||||
if( ISDIGIT(*q) )
|
||||
if( ISDIGIT(*q) )
|
||||
{
|
||||
++q;
|
||||
// and next character
|
||||
@ -632,7 +632,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr)
|
||||
--q;
|
||||
}
|
||||
// skip the sequencer and search again
|
||||
p = q+1;
|
||||
p = q+1;
|
||||
break;
|
||||
}// end while
|
||||
}
|
||||
@ -668,7 +668,7 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap)
|
||||
#if defined(DEBUGLOGMAP) || defined(DEBUGLOGCHAR) || defined(DEBUGLOGLOGIN)
|
||||
FILE *fp;
|
||||
#endif
|
||||
|
||||
|
||||
if (!string || *string == '\0') {
|
||||
ShowError("Empty string passed to _vShowMessage().\n");
|
||||
return 1;
|
||||
|
||||
@ -867,7 +867,7 @@ int do_sockets(int next)
|
||||
if (last_tick != socket_data_last_tick)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
|
||||
sprintf(buf, "In: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | Out: %.03f kB/s (%.03f kB/s, Q: %.03f kB) | RAM: %.03f MB", socket_data_i/1024., socket_data_ci/1024., socket_data_qi/1024., socket_data_o/1024., socket_data_co/1024., socket_data_qo/1024., malloc_usage()/1024.);
|
||||
#ifdef _WIN32
|
||||
SetConsoleTitle(buf);
|
||||
@ -1244,7 +1244,7 @@ int socket_getips(uint32* ips, int max)
|
||||
|
||||
#ifdef WIN32
|
||||
{
|
||||
char fullhost[255];
|
||||
char fullhost[255];
|
||||
|
||||
// XXX This should look up the local IP addresses in the registry
|
||||
// instead of calling gethostbyname. However, the way IP addresses
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
// For more information, see LICENCE in the main folder
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include "winapi.h"
|
||||
#endif
|
||||
@ -34,7 +34,7 @@ typedef struct __declspec( align(64) ) SPIN_LOCK{
|
||||
typedef struct SPIN_LOCK{
|
||||
volatile int32 lock;
|
||||
volatile int32 nest; // nesting level.
|
||||
|
||||
|
||||
volatile int32 sync_lock;
|
||||
} __attribute__((aligned(64))) SPIN_LOCK, *PSPIN_LOCK;
|
||||
#endif
|
||||
@ -57,8 +57,8 @@ static forceinline void FinalizeSpinLock(PSPIN_LOCK lck){
|
||||
|
||||
static forceinline void EnterSpinLock(PSPIN_LOCK lck){
|
||||
int tid = rathread_get_tid();
|
||||
|
||||
// Get Sync Lock && Check if the requester thread already owns the lock.
|
||||
|
||||
// Get Sync Lock && Check if the requester thread already owns the lock.
|
||||
// if it owns, increase nesting level
|
||||
getsynclock(&lck->sync_lock);
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){
|
||||
@ -68,17 +68,17 @@ static forceinline void EnterSpinLock(PSPIN_LOCK lck){
|
||||
}
|
||||
// drop sync lock
|
||||
dropsynclock(&lck->sync_lock);
|
||||
|
||||
|
||||
// Spin until we've got it !
|
||||
|
||||
|
||||
// Spin until we've got it !
|
||||
while(1){
|
||||
|
||||
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){
|
||||
|
||||
|
||||
InterlockedIncrement(&lck->nest);
|
||||
return; // Got Lock
|
||||
}
|
||||
|
||||
|
||||
rathread_yield(); // Force ctxswitch to another thread.
|
||||
}
|
||||
|
||||
@ -89,12 +89,12 @@ static forceinline void LeaveSpinLock(PSPIN_LOCK lck){
|
||||
int tid = rathread_get_tid();
|
||||
|
||||
getsynclock(&lck->sync_lock);
|
||||
|
||||
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ // this thread owns the lock.
|
||||
if(InterlockedDecrement(&lck->nest) == 0)
|
||||
InterlockedExchange(&lck->lock, 0); // Unlock!
|
||||
}
|
||||
|
||||
|
||||
dropsynclock(&lck->sync_lock);
|
||||
}
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ static int Sql_P_Keepalive(Sql* self);
|
||||
* @param host : hostname
|
||||
* @param port : port
|
||||
* @param db : schema name
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db)
|
||||
{
|
||||
|
||||
@ -210,10 +210,10 @@ void Sql_Free(Sql* self);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Prepared Statements
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Parameters are placed in the statement by embedding question mark ('?')
|
||||
// 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
|
||||
// The markers cannot be inside quotes. Quotes will be added automatically
|
||||
// when they are required.
|
||||
//
|
||||
// example queries with parameters:
|
||||
@ -298,7 +298,7 @@ size_t SqlStmt_NumColumns(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
|
||||
/// 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
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#ifdef WIN32
|
||||
#include "winapi.h"
|
||||
#define getpagesize() 4096 // @TODO: implement this properly (GetSystemInfo .. dwPageSize..). (Atm as on all supported win platforms its 4k its static.)
|
||||
#define __thread __declspec( thread )
|
||||
#define __thread __declspec( thread )
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -25,8 +25,8 @@
|
||||
#include "thread.h"
|
||||
|
||||
// When Compiling using MSC (on win32..) we know we have support in any case!
|
||||
#ifdef _MSC_VER
|
||||
#define HAS_TLS
|
||||
#ifdef _MSC_VER
|
||||
#define HAS_TLS
|
||||
#endif
|
||||
|
||||
|
||||
@ -34,10 +34,10 @@
|
||||
|
||||
struct rAthread {
|
||||
unsigned int myID;
|
||||
|
||||
|
||||
RATHREAD_PRIO prio;
|
||||
rAthreadProc proc;
|
||||
void *param;
|
||||
void *param;
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE hThread;
|
||||
@ -60,7 +60,7 @@ static struct rAthread l_threads[RA_THREADS_MAX];
|
||||
void rathread_init(){
|
||||
register unsigned int i;
|
||||
memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread) );
|
||||
|
||||
|
||||
for(i = 0; i < RA_THREADS_MAX; i++){
|
||||
l_threads[i].myID = i;
|
||||
}
|
||||
@ -78,10 +78,10 @@ void rathread_init(){
|
||||
|
||||
void rathread_final(){
|
||||
register unsigned int i;
|
||||
|
||||
// Unterminated Threads Left?
|
||||
|
||||
// Unterminated Threads Left?
|
||||
// Should'nt happen ..
|
||||
// Kill 'em all!
|
||||
// Kill 'em all!
|
||||
//
|
||||
for(i = 1; i < RA_THREADS_MAX; i++){
|
||||
if(l_threads[i].proc != NULL){
|
||||
@ -89,8 +89,8 @@ void rathread_final(){
|
||||
rathread_destroy(&l_threads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}//end: rathread_final()
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ static void rat_thread_terminated( rAthread handle ){
|
||||
|
||||
// Simply set all members to 0 (except the id)
|
||||
memset(handle, 0x00, sizeof(struct rAthread));
|
||||
|
||||
|
||||
handle->myID = id_backup; // done ;)
|
||||
|
||||
}//end: rat_thread_terminated()
|
||||
@ -114,15 +114,15 @@ static void *_raThreadMainRedirector( void *p ){
|
||||
sigset_t set; // on Posix Thread platforms
|
||||
#endif
|
||||
void *ret;
|
||||
|
||||
|
||||
// Update myID @ TLS to right id.
|
||||
#ifdef HAS_TLS
|
||||
g_rathread_ID = ((rAthread)p)->myID;
|
||||
g_rathread_ID = ((rAthread)p)->myID;
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
// When using posix threads
|
||||
// the threads inherits the Signal mask from the thread which's spawned
|
||||
// the threads inherits the Signal mask from the thread which's spawned
|
||||
// this thread
|
||||
// so we've to block everything we dont care about.
|
||||
sigemptyset(&set);
|
||||
@ -131,13 +131,13 @@ static void *_raThreadMainRedirector( void *p ){
|
||||
sigaddset(&set, SIGPIPE);
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ret = ((rAthread)p)->proc( ((rAthread)p)->param ) ;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef WIN32
|
||||
CloseHandle( ((rAthread)p)->hThread );
|
||||
#endif
|
||||
|
||||
@ -155,7 +155,7 @@ static void *_raThreadMainRedirector( void *p ){
|
||||
|
||||
///
|
||||
/// API Level
|
||||
///
|
||||
///
|
||||
rAthread rathread_create( rAthreadProc entryPoint, void *param ){
|
||||
return rathread_createEx( entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL );
|
||||
}//end: rathread_create()
|
||||
@ -176,21 +176,21 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta
|
||||
szStack += tmp;
|
||||
|
||||
|
||||
// Get a free Thread Slot.
|
||||
// Get a free Thread Slot.
|
||||
for(i = 0; i < RA_THREADS_MAX; i++){
|
||||
if(l_threads[i].proc == NULL){
|
||||
handle = &l_threads[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(handle == NULL){
|
||||
ShowError("rAthread: cannot create new thread (entryPoint: %p) - no free thread slot found!", entryPoint);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
handle->proc = entryPoint;
|
||||
handle->param = param;
|
||||
|
||||
@ -199,7 +199,7 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta
|
||||
#else
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, szStack);
|
||||
|
||||
|
||||
if(pthread_create(&handle->hThread, &attr, _raThreadMainRedirector, (void*)handle) != 0){
|
||||
handle->proc = NULL;
|
||||
handle->param = NULL;
|
||||
@ -209,7 +209,7 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta
|
||||
#endif
|
||||
|
||||
rathread_prio_set( handle, prio );
|
||||
|
||||
|
||||
return handle;
|
||||
}//end: rathread_createEx
|
||||
|
||||
@ -222,11 +222,11 @@ void rathread_destroy ( rAthread handle ){
|
||||
}
|
||||
#else
|
||||
if( pthread_cancel( handle->hThread ) == 0){
|
||||
|
||||
|
||||
// We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread.
|
||||
//
|
||||
//
|
||||
pthread_join( handle->hThread, NULL );
|
||||
|
||||
|
||||
// Tell our manager to release ressources ;)
|
||||
rat_thread_terminated(handle);
|
||||
}
|
||||
@ -236,11 +236,11 @@ void rathread_destroy ( rAthread handle ){
|
||||
rAthread rathread_self( ){
|
||||
#ifdef HAS_TLS
|
||||
rAthread handle = &l_threads[g_rathread_ID];
|
||||
|
||||
if(handle->proc != NULL) // entry point set, so its used!
|
||||
|
||||
if(handle->proc != NULL) // entry point set, so its used!
|
||||
return handle;
|
||||
#else
|
||||
// .. so no tls means we have to search the thread by its api-handle ..
|
||||
// .. so no tls means we have to search the thread by its api-handle ..
|
||||
int i;
|
||||
|
||||
#ifdef WIN32
|
||||
@ -250,21 +250,21 @@ rAthread rathread_self( ){
|
||||
pthread_t hSelf;
|
||||
hSelf = pthread_self();
|
||||
#endif
|
||||
|
||||
|
||||
for(i = 0; i < RA_THREADS_MAX; i++){
|
||||
if(l_threads[i].hThread == hSelf && l_threads[i].proc != NULL)
|
||||
return &l_threads[i];
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
}//end: rathread_self()
|
||||
|
||||
|
||||
int rathread_get_tid(){
|
||||
|
||||
#ifdef HAS_TLS
|
||||
#ifdef HAS_TLS
|
||||
return g_rathread_ID;
|
||||
#else
|
||||
// todo
|
||||
@ -273,21 +273,21 @@ int rathread_get_tid(){
|
||||
#else
|
||||
return (intptr_t)pthread_self();
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}//end: rathread_get_tid()
|
||||
|
||||
|
||||
bool rathread_wait( rAthread handle, void* *out_exitCode ){
|
||||
|
||||
|
||||
// Hint:
|
||||
// no thread data cleanup routine call here!
|
||||
// its managed by the callProxy itself..
|
||||
//
|
||||
#ifdef WIN32
|
||||
WaitForSingleObject(handle->hThread, INFINITE);
|
||||
return true;
|
||||
return true;
|
||||
#else
|
||||
if(pthread_join(handle->hThread, out_exitCode) == 0)
|
||||
return true;
|
||||
@ -298,8 +298,8 @@ bool rathread_wait( rAthread handle, void* *out_exitCode ){
|
||||
|
||||
|
||||
void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio ){
|
||||
handle->prio = RAT_PRIO_NORMAL;
|
||||
//@TODO
|
||||
handle->prio = RAT_PRIO_NORMAL;
|
||||
//@TODO
|
||||
}//end: rathread_prio_set()
|
||||
|
||||
|
||||
@ -309,9 +309,9 @@ RATHREAD_PRIO rathread_prio_get( rAthread handle){
|
||||
|
||||
|
||||
void rathread_yield(){
|
||||
#ifdef WIN32
|
||||
#ifdef WIN32
|
||||
SwitchToThread();
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
#endif
|
||||
}//end: rathread_yield()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#pragma once
|
||||
#pragma once
|
||||
#ifndef _rA_THREAD_H_
|
||||
#define _rA_THREAD_H_
|
||||
|
||||
@ -13,7 +13,7 @@ typedef void* (*rAthreadProc)(void*);
|
||||
typedef enum RATHREAD_PRIO {
|
||||
RAT_PRIO_LOW = 0,
|
||||
RAT_PRIO_NORMAL,
|
||||
RAT_PRIO_HIGH
|
||||
RAT_PRIO_HIGH
|
||||
} RATHREAD_PRIO;
|
||||
|
||||
|
||||
@ -22,18 +22,18 @@ typedef enum RATHREAD_PRIO {
|
||||
*
|
||||
* @param entyPoint - entryProc,
|
||||
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint.
|
||||
*
|
||||
*
|
||||
* @return not NULL if success
|
||||
*/
|
||||
rAthread rathread_create( rAthreadProc entryPoint, void *param );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a new Thread (with more creation options)
|
||||
*
|
||||
* @param entyPoint - entryProc,
|
||||
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint
|
||||
* @param szStack - stack Size in bytes
|
||||
* @param szStack - stack Size in bytes
|
||||
* @param prio - Priority of the Thread @ OS Scheduler..
|
||||
*
|
||||
* @return not NULL if success
|
||||
@ -44,29 +44,29 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta
|
||||
/**
|
||||
* Destroys the given Thread immediatly
|
||||
*
|
||||
* @note The Handle gets invalid after call! dont use it afterwards.
|
||||
* @note The Handle gets invalid after call! dont use it afterwards.
|
||||
*
|
||||
* @param handle - thread to destroy.
|
||||
*/
|
||||
void rathread_destroy ( rAthread handle );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the thread handle of the thread calling this function
|
||||
*
|
||||
*
|
||||
* @note this wont work @ programms main thread
|
||||
* @note the underlying implementation might not perform very well, cache the value received!
|
||||
*
|
||||
* @note the underlying implementation might not perform very well, cache the value received!
|
||||
*
|
||||
* @return not NULL if success
|
||||
*/
|
||||
rAthread rathread_self( );
|
||||
|
||||
|
||||
/**
|
||||
* Returns own thrad id (TID)
|
||||
* Returns own thrad id (TID)
|
||||
*
|
||||
* @note this is an unique identifier for the calling thread, and
|
||||
* depends on platfrom / compiler, and may not be the systems Thread ID!
|
||||
* @note this is an unique identifier for the calling thread, and
|
||||
* depends on platfrom / compiler, and may not be the systems Thread ID!
|
||||
*
|
||||
* @return -1 when fails, otherwise >= 0
|
||||
*/
|
||||
@ -74,26 +74,26 @@ int rathread_get_tid();
|
||||
|
||||
|
||||
/**
|
||||
* Waits for the given thread to terminate
|
||||
* Waits for the given thread to terminate
|
||||
*
|
||||
* @param handle - thread to wait (join) for
|
||||
* @param out_Exitcode - [OPTIONAL] - if given => Exitcode (value) of the given thread - if it's terminated
|
||||
*
|
||||
*
|
||||
* @return true - if the given thread has been terminated.
|
||||
*/
|
||||
bool rathread_wait( rAthread handle, void* *out_exitCode );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the given PRIORITY @ OS Task Scheduler
|
||||
*
|
||||
*
|
||||
* @param handle - thread to set prio for
|
||||
* @param rio - the priority (RAT_PRIO_LOW ... )
|
||||
*/
|
||||
void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets the current Prio of the given trhead
|
||||
*
|
||||
* @param handle - the thread to get the prio for.
|
||||
@ -103,9 +103,9 @@ RATHREAD_PRIO rathread_prio_get( rAthread handle);
|
||||
|
||||
/**
|
||||
* Tells the OS scheduler to yield the execution of the calling thread
|
||||
*
|
||||
*
|
||||
* @note: this will not "pause" the thread,
|
||||
* it just allows the OS to spent the remaining time
|
||||
* it just allows the OS to spent the remaining time
|
||||
* of the slice to another thread.
|
||||
*/
|
||||
void rathread_yield();
|
||||
|
||||
@ -427,7 +427,7 @@ void split_time(int timein, int* year, int* month, int* day, int* hour, int* min
|
||||
const int factor_min = 60;
|
||||
const int factor_hour = factor_min*60;
|
||||
const int factor_day = factor_hour*24;
|
||||
const int factor_month = 2629743; // Approx (30.44 days)
|
||||
const int factor_month = 2629743; // Approx (30.44 days)
|
||||
const int factor_year = 31556926; // Approx (365.24 days)
|
||||
|
||||
*year = timein/factor_year;
|
||||
@ -459,7 +459,7 @@ double solve_time(char* modif_p) {
|
||||
time_t now = time(NULL);
|
||||
time_t then = now;
|
||||
then_tm = *localtime(&then);
|
||||
|
||||
|
||||
nullpo_retr(0,modif_p);
|
||||
|
||||
while (modif_p[0] != '\0') {
|
||||
|
||||
@ -60,7 +60,7 @@ void ShowDump(const void* buffer, size_t length)
|
||||
|
||||
ShowDebug("--- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F 0123456789ABCDEF\n");
|
||||
ascii[16] = 0;
|
||||
|
||||
|
||||
for( i = 0; i < length; i++ )
|
||||
{
|
||||
char c = RBUFB(buffer,i);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#define WINVER 0x0500
|
||||
#define _WIN32_IE 0x0600
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOCOMM
|
||||
#define NOCOMM
|
||||
#define NOKANJI
|
||||
#define NOHELP
|
||||
#define NOMCX
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user