Update timers support

Always WIN32/WINCE threading or windows platforms (semaphore, mutex and events) and remove pthread dependency.
Resolve some issues.
This commit is contained in:
bossiel 2009-12-17 01:11:20 +00:00
parent 3da5926e38
commit ada4488146
33 changed files with 1191 additions and 354 deletions

View File

@ -46,17 +46,13 @@
*
* @return Zero if succeed and nonzero error code otherwise.
**/
int tnet_socket_close(const tnet_socket_t *sock)
int tnet_socket_close(tnet_socket_t *sock)
{
#if TNET_UNDER_WINDOWS
return closesocket(sock->fd);
#else
return close(sock->fd);
#endif
return tnet_sockfd_close(&(sock->fd));
}
int tnet_socket_stream_connectto(tnet_socket_tcp_t *sock, const char* host, uint16_t port)
int tnet_socket_stream_connectto(tnet_socket_tcp_t *sock, const char* host, tnet_port_t port)
{
int status = 0;
tsk_istr_t _port;
@ -134,17 +130,17 @@ static void* tnet_socket_create(void * self, va_list * app)
struct addrinfo *result = 0;
struct addrinfo *ptr = 0;
struct addrinfo hints;
tnet_hostname_t local_hostname;
tnet_host_t local_hostname;
const char *host = va_arg(*app, const char*);
sock->port = va_arg(*app, uint16_t);
sock->port = va_arg(*app, tnet_port_t);
tsk_itoa(sock->port, &port);
sock->type = va_arg(*app, tnet_socket_type_t);
/* Get the local host name */
memset(local_hostname, 0, sizeof(local_hostname));
if(host && !tsk_strempty(host))
if(host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host))
{
memset(local_hostname, 0, sizeof(local_hostname));
memcpy(local_hostname, host, strlen(host)>sizeof(local_hostname)-1 ? sizeof(local_hostname)-1 : strlen(host));
}
else
@ -177,12 +173,31 @@ static void* tnet_socket_create(void * self, va_list * app)
{
sock->fd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
/* Get local IP string. */
if(status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->hostname, sizeof(sock->hostname), 0, 0, NI_NUMERICHOST))
if(status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST))
{
TNET_PRINT_LAST_ERROR();
goto bail;
tnet_socket_close(sock);
continue;
}
else
{
if(status = bind(sock->fd, ptr->ai_addr, ptr->ai_addrlen))
{
TNET_PRINT_LAST_ERROR();
tnet_socket_close(sock);
continue;
}
else
{
if(sock->port == TNET_SOCKET_PORT_ANY && (status = tnet_get_port(sock->fd, &(sock->port))))
{
TNET_PRINT_LAST_ERROR();
tnet_socket_close(sock);
continue;
}
else break;
}
}
break;
}
}
@ -191,23 +206,7 @@ static void* tnet_socket_create(void * self, va_list * app)
{
TNET_PRINT_LAST_ERROR();
goto bail;
}
/* Bind to the specified address and port. */
if(bind(sock->fd, result->ai_addr, result->ai_addrlen))
{
TNET_PRINT_LAST_ERROR();
tnet_socket_close(sock);
sock->fd = 0;
goto bail;
}
else
{
if(!sock->port && (status = tnet_getPort(sock->fd, &(sock->port))))
{
TNET_PRINT_LAST_ERROR();
}
}
}
/* To avoid "Address already in use" error */
{

View File

@ -48,7 +48,7 @@
* @param self The socket to free.
* @sa TNET_SOCKET_CREATE.
*/
#define TNET_SOCKET_CREATE(host, port, type) tsk_object_new(tnet_socket_def_t, (const char*)host, (uint16_t)port, (tnet_socket_type_t)type)
#define TNET_SOCKET_CREATE(host, port, type) tsk_object_new(tnet_socket_def_t, (const char*)host, (tnet_port_t)port, (tnet_socket_type_t)type)
#define TNET_SOCKET_SAFE_FREE(self) tsk_object_unref(self), self = 0
/**
@ -109,6 +109,9 @@ tnet_socket_type_t;
#define TNET_SOCKET_TYPE_IS_SECURE(type) (TNET_SOCKET_TYPE_IS_IPSEC(type) || TNET_SOCKET_TYPE_IS_TLS(type) )
#define TNET_SOCKET_HOST_ANY 0
#define TNET_SOCKET_PORT_ANY 0
/*==
* tnet_socket_t
* type: Defines the socket type.
@ -121,8 +124,8 @@ tnet_socket_type_t;
#define TNET_DECLARE_SOCKET struct { \
TSK_DECLARE_OBJECT; \
tnet_socket_type_t type; \
int32_t fd; \
tnet_hostname_t hostname; \
tnet_fd_t fd; \
tnet_ip_t ip; \
uint16_t port; \
}
typedef TNET_DECLARE_SOCKET tnet_socket_t; /**< Socket structure definition. */
@ -132,7 +135,7 @@ typedef tnet_socket_t tnet_socket_tls_t; /**< TLS socket. */
typedef tnet_socket_t tnet_socket_ipsec_t; /**< IPSec socket. */
typedef tsk_list_t tnet_sockets_L_t; /**< List of @ref tnet_socket_t elements. */
TINYNET_API int tnet_socket_stream_connectto(tnet_socket_tcp_t *socket, const char* host, uint16_t port);
TINYNET_API int tnet_socket_stream_connectto(tnet_socket_tcp_t *socket, const char* host, tnet_port_t port);
TINYNET_API int tnet_socket_dgram_sendto(tnet_socket_tcp_t *socket, const struct sockaddr *to, const void* buf, size_t size);

View File

@ -39,8 +39,7 @@
typedef struct tnet_transport_s
{
tnet_socket_t *server;
tnet_socket_t *client;
tnet_socket_t *master;
void *context;
@ -48,18 +47,17 @@ typedef struct tnet_transport_s
char *description;
unsigned running:1;
unsigned connected:1;
}
tnet_transport_t;
static void *tnet_transport_thread(void *param);
tnet_transport_handle_t* tnet_transport_start(const char* host, uint16_t port, tnet_socket_type_t type, const char* description)
tnet_transport_handle_t* tnet_transport_start(const char* host, tnet_port_t port, tnet_socket_type_t type, const char* description)
{
int err;
tnet_transport_t *transport = tsk_object_new(tnet_transport_def_t, host, port, type, description);
if(!TNET_SOCKET_IS_VALID(transport->server))
if(!TNET_SOCKET_IS_VALID(transport->master))
{
tsk_object_unref(transport);
TSK_DEBUG_ERROR("Failed to create new transport.");
@ -73,23 +71,24 @@ tnet_transport_handle_t* tnet_transport_start(const char* host, uint16_t port, t
TSK_DEBUG_FATAL("Failed to start transport thread with error: %d\n", err);
return 0;
}
while(!transport->running) tsk_thread_sleep(500);
transport->running = 1;
return transport;
}
int tnet_transport_get_isconnected(const tnet_transport_handle_t *handle)
int tnet_transport_isrunning(const tnet_transport_handle_t *handle)
{
if(handle)
{
const tnet_transport_t *transport = handle;
return transport->connected;
return transport->running;
}
else
{
TSK_DEBUG_ERROR("NULL transport object.");
return 0;
}
return 0;
}
const char* tnet_transport_get_description(const tnet_transport_handle_t *handle)
@ -102,50 +101,22 @@ const char* tnet_transport_get_description(const tnet_transport_handle_t *handle
else
{
TSK_DEBUG_ERROR("NULL transport object.");
return 0;
}
return 0;
}
uint16_t tnet_transport_get_local_port(const tnet_transport_handle_t *handle, int client)
int tnet_transport_get_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port)
{
if(handle)
{
const tnet_transport_t *transport = handle;
if(TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type) || !client)
{
return transport->server->port;
}
else
{
return (client && transport->client) ? transport->client->port : 0;
}
return tnet_get_ip_n_port(fd, ip, port);
}
else
{
TSK_DEBUG_ERROR("NULL transport object.");
}
return 0;
}
const char* tnet_transport_get_local_ip(const tnet_transport_handle_t *handle, int client)
{
if(handle)
{
const tnet_transport_t *transport = handle;
if(TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type) || !client)
{
return transport->server->hostname;
}
else
{
return (client && transport->client) ? transport->client->hostname : 0;
}
}
else
{
TSK_DEBUG_ERROR("NULL transport object.");
}
return 0;
return -1;
}
tnet_socket_type_t tnet_transport_get_socket_type(const tnet_transport_handle_t *handle)
@ -153,7 +124,7 @@ tnet_socket_type_t tnet_transport_get_socket_type(const tnet_transport_handle_t
if(handle)
{
const tnet_transport_t *transport = handle;
transport->server->type;
transport->master->type;
}
else
{
@ -184,7 +155,7 @@ static void* tnet_transport_create(void * self, va_list * app)
if(transport)
{
const char *host = va_arg(*app, const char*);
uint16_t port = va_arg(*app, uint16_t);
uint16_t port = va_arg(*app, tnet_port_t);
tnet_socket_type_t type = va_arg(*app, tnet_socket_type_t);
const char *description = va_arg(*app, const char*);
@ -193,8 +164,7 @@ static void* tnet_transport_create(void * self, va_list * app)
transport->description = tsk_strdup(description);
}
transport->server = TNET_SOCKET_CREATE(host, port, type);
transport->client = 0;
transport->master = TNET_SOCKET_CREATE(host, port, type);
}
return self;
}
@ -204,7 +174,7 @@ static void* tnet_transport_destroy(void * self)
tnet_transport_t *transport = self;
if(transport)
{
TNET_SOCKET_SAFE_FREE(transport->server);
TNET_SOCKET_SAFE_FREE(transport->master);
TSK_FREE(transport->description);
}
@ -269,7 +239,10 @@ const void *tnet_transport_def_t = &tnet_transport_def_s;
typedef struct tnet_socket_desc_s
{
WSABUF wsaBuffer;
int32_t fd;
tnet_fd_t fd;
unsigned connected:1;
tnet_transport_data_read callback;
DWORD readCount;
DWORD writeCount;
@ -279,15 +252,16 @@ tnet_socket_desc_t;
/*== Transport context structure definition */
typedef struct tnet_transport_ctx_s
{
DWORD eventsCount;
size_t eventsCount;
WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
tnet_socket_desc_t* sockets[WSA_MAXIMUM_WAIT_EVENTS];
}
tnet_transport_ctx_t;
/*== Add socket */
static void tnet_socket_desc_add(int32_t fd, tnet_transport_ctx_t *context)
static void tnet_socket_desc_add(tnet_fd_t fd, tnet_transport_ctx_t *context)
{
// FIXME: LOCK
tnet_socket_desc_t *socket_desc = tsk_calloc(1, sizeof(tnet_socket_desc_t));
socket_desc->fd = fd;
@ -300,9 +274,26 @@ static void tnet_socket_desc_add(int32_t fd, tnet_transport_ctx_t *context)
/*== Remove socket */
static void tnet_socket_desc_remove(int index, tnet_transport_ctx_t *context)
{
// FIXME: LOCK
}
/*== Set callback */
static int tnet_socket_desc_setcb(tnet_transport_ctx_t *context, tnet_fd_t fd, tnet_transport_data_read cb)
{
// FIXME: LOCK
size_t i;
for(i=0; i<context->eventsCount; i++)
{
if(context->sockets[i]->fd == fd)
{
context->sockets[i]->callback = cb;
return 0;
}
}
return -1;
}
/*=== */
int CALLBACK AcceptCondFunc(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS lpSQos, LPQOS lpGQos, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData, GROUP FAR *Group, DWORD CallbackData)
{
@ -312,7 +303,7 @@ int CALLBACK AcceptCondFunc(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS lp
/* == Register new socket */
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, int32_t fd)
int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd)
{
tnet_transport_t *transport = (tnet_transport_t*)handle;
tnet_transport_ctx_t *context;
@ -339,94 +330,93 @@ int tnet_transport_add_socket(const tnet_transport_handle_t *handle, int32_t fd)
return 0;
}
/*== Connect stream socket to the specified destination. */
int tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, uint16_t port)
/*== Connect stream/datagram socket to the specified destination. */
tnet_fd_t tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, tnet_port_t port)
{
tnet_transport_t *transport = (tnet_transport_t*)handle;
struct sockaddr to;
int ret = -1;
struct sockaddr_storage to;
int status = -1;
tnet_fd_t fd = INVALID_SOCKET;
if(!transport)
{
TSK_DEBUG_ERROR("Invalid server handle.");
return ret;
goto bail;
}
if(!TNET_SOCKET_TYPE_IS_STREAM(transport->server->type))
/* Init destination sockaddr fields */
if(status = tnet_sockaddr_init(host, port, transport->master->type, &to))
{
TSK_DEBUG_ERROR("In order to use WSAConnect you must use a stream transport.");
return ret;
TSK_DEBUG_ERROR("Invalid HOST/PORT.");
goto bail;
}
if(transport->connected || transport->client)
/*
* STREAM ==> create new socket add connect it to the remote host.
* DGRAM ==> connect the master to the remote host.
*/
if(TNET_SOCKET_TYPE_IS_STREAM(transport->master->type))
{
/* Create socket descriptor. */
if(status = tnet_sockfd_init(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, transport->master->type, &fd))
{
TSK_DEBUG_ERROR("Failed to create new sockfd.");
goto bail;
}
/* Add the socket */
if(status = tnet_transport_add_socket(handle, fd))
{
TNET_PRINT_LAST_ERROR();
tnet_sockfd_close(&fd);
goto bail;
}
}
else
{
TSK_DEBUG_ERROR("Transport already connected.");
return ret;
fd = transport->master->fd;
}
/* Init sockaddr fields */
if(tnet_sockaddr_init(host, port, transport->server->type, &to))
if((status = WSAConnect(fd, (LPSOCKADDR)&to, sizeof(to), NULL, NULL, NULL, NULL)) == SOCKET_ERROR)
{
TSK_DEBUG_ERROR("Invalid host or port.");
return ret;
}
/* Create client socket. */
transport->client = TNET_SOCKET_CREATE(0, 0, transport->server->type);
if(!TNET_SOCKET_IS_VALID(transport->client) || tnet_transport_add_socket(handle, transport->client->fd))
{
TNET_PRINT_LAST_ERROR();
TNET_SOCKET_SAFE_FREE(transport->client);
return ret;
}
if((ret = WSAConnect(transport->client->fd, (LPSOCKADDR)&to, sizeof(to), NULL, NULL, NULL, NULL)) == SOCKET_ERROR)
{
if((ret = WSAGetLastError()) == WSAEWOULDBLOCK)
if((status = WSAGetLastError()) == WSAEWOULDBLOCK)
{
TSK_DEBUG_INFO("WSAEWOULDBLOCK error for WSAConnect operation");
ret = 0;
status = 0;
}
else
{
TNET_PRINT_LAST_ERROR();
return ret;
tnet_sockfd_close(&fd);
goto bail;
}
} else ret = 0;
}
return ret;
bail:
return fd;
}
/*== send stream data to the remote peer*/
int tnet_transport_send(const tnet_transport_handle_t *handle, const void* buf, size_t size)
size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t from, const void* buf, size_t size)
{
tnet_transport_t *transport = (tnet_transport_t*)handle;
int ret = -1;
WSABUF wsaBuffer;
DWORD numberOfBytesSent;
DWORD numberOfBytesSent = 0;
if(!transport)
{
TSK_DEBUG_ERROR("Invalid transport handle.");
return ret;
}
if(!transport->connected || !transport->client)
{
TSK_DEBUG_ERROR("You MUST connect first.");
return ret;
}
if(!TNET_SOCKET_TYPE_IS_STREAM(transport->client->type))
{
TSK_DEBUG_ERROR("In order to use WSASend you must use a stream transport.");
return ret;
goto bail;
}
wsaBuffer.buf = (CHAR*)buf;
wsaBuffer.len = size;
if((ret = WSASend(transport->client->fd, &wsaBuffer, 1, &numberOfBytesSent, 0, NULL, NULL)) == SOCKET_ERROR)
if((ret = WSASend(from, &wsaBuffer, 1, &numberOfBytesSent, 0, NULL, NULL)) == SOCKET_ERROR)
{
if((ret = WSAGetLastError()) == WSAEWOULDBLOCK)
{
@ -436,19 +426,23 @@ int tnet_transport_send(const tnet_transport_handle_t *handle, const void* buf,
else
{
TNET_PRINT_LAST_ERROR();
return ret;
}
}else ret = 0;
return ret;
//tnet_sockfd_close(&from);
goto bail;
}
}
else ret = 0;
bail:
return numberOfBytesSent;
}
/*== send dgarm to the specified destionation */
int tnet_transport_sendto(const tnet_transport_handle_t *handle, const struct sockaddr *to, const void* buf, size_t size)
size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_t from, const struct sockaddr *to, const void* buf, size_t size)
{
tnet_transport_t *transport = (tnet_transport_t*)handle;
WSABUF wsaBuffer;
DWORD numberOfBytesSent;
DWORD numberOfBytesSent = 0;
int ret = -1;
if(!transport)
@ -457,7 +451,7 @@ int tnet_transport_sendto(const tnet_transport_handle_t *handle, const struct so
return ret;
}
if(!TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type))
if(!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type))
{
TSK_DEBUG_ERROR("In order to use WSASendTo you must use an udp transport.");
return ret;
@ -466,7 +460,7 @@ int tnet_transport_sendto(const tnet_transport_handle_t *handle, const struct so
wsaBuffer.buf = (CHAR*)buf;
wsaBuffer.len = size;
if((ret = WSASendTo(transport->server->fd, &wsaBuffer, 1, &numberOfBytesSent, 0, to, sizeof(*to), 0, 0)) == SOCKET_ERROR)
if((ret = WSASendTo(from, &wsaBuffer, 1, &numberOfBytesSent, 0, to, sizeof(*to), 0, 0)) == SOCKET_ERROR)
{
if((ret = WSAGetLastError()) == WSAEWOULDBLOCK)
{
@ -480,9 +474,24 @@ int tnet_transport_sendto(const tnet_transport_handle_t *handle, const struct so
}
} else ret = 0;
TSK_DEBUG_INFO("[%s] %d bytes have been sent using WSASendTo", transport->description, numberOfBytesSent);
//TSK_DEBUG_INFO("[%s] %d bytes have been sent using WSASendTo", transport->description, numberOfBytesSent);
return ret;
return numberOfBytesSent;
}
/*=== Sets callback function to call when data arrive on the specified sockfd. */
int tnet_transport_set_callback(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_transport_data_read callback)
{
tnet_transport_t *transport = (tnet_transport_t*)handle;
int ret = -1;
if(!transport)
{
TSK_DEBUG_ERROR("Invalid server handle.");
return ret;
}
return tnet_socket_desc_setcb(transport->context, fd, callback);
}
/*=== Main thread */
@ -499,9 +508,9 @@ static void *tnet_transport_thread(void *param)
transport->context = context;
/* Start listening */
if(TNET_SOCKET_TYPE_IS_STREAM(transport->server->type))
if(TNET_SOCKET_TYPE_IS_STREAM(transport->master->type))
{
if(listen(transport->server->fd, WSA_MAXIMUM_WAIT_EVENTS))
if(listen(transport->master->fd, WSA_MAXIMUM_WAIT_EVENTS))
{
TNET_PRINT_LAST_ERROR();
goto bail;
@ -509,14 +518,15 @@ static void *tnet_transport_thread(void *param)
}
/* Add the current the transport socket to the context. */
tnet_socket_desc_add(transport->server->fd, context);
if(ret = WSAEventSelect(transport->server->fd, context->events[context->eventsCount - 1], TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type) ? FD_READ : FD_ALL_EVENTS/*FD_ACCEPT | FD_READ | FD_CONNECT | FD_CLOSE*/) == SOCKET_ERROR)
tnet_socket_desc_add(transport->master->fd, context);
if(ret = WSAEventSelect(transport->master->fd, context->events[context->eventsCount - 1], TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) ? FD_READ : FD_ALL_EVENTS/*FD_ACCEPT | FD_READ | FD_CONNECT | FD_CLOSE*/) == SOCKET_ERROR)
{
TNET_PRINT_LAST_ERROR();
goto bail;
}
TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d}...", transport->description, transport->server->hostname, transport->server->port);
TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d}...", transport->description, transport->master->ip, transport->master->port);
transport->running = 1;
while(transport->running)
{
@ -551,7 +561,7 @@ static void *tnet_transport_thread(void *param)
/*================== FD_ACCEPT ==================*/
if(networkEvents.lNetworkEvents & FD_ACCEPT)
{
int32_t fd;
tnet_fd_t fd;
TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT", transport->description);
@ -589,7 +599,7 @@ static void *tnet_transport_thread(void *param)
/*================== FD_CONNECT ==================*/
if(networkEvents.lNetworkEvents & FD_CONNECT)
{
//int32_t fd;
//tnet_fd_t fd;
TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CONNECT", transport->description);
@ -601,10 +611,7 @@ static void *tnet_transport_thread(void *param)
}
else
{
if(!transport->connected)
{
transport->connected = 1;
}
active_socket->connected = 1;
}
}
@ -624,7 +631,7 @@ static void *tnet_transport_thread(void *param)
/* Create socket's internal buffer. */
if(!active_socket->wsaBuffer.buf)
{
size_t max_buffer_size = TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type) ? DGRAM_MAX_SIZE : STREAM_MAX_SIZE;
size_t max_buffer_size = TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) ? DGRAM_MAX_SIZE : STREAM_MAX_SIZE;
active_socket->wsaBuffer.buf = tsk_calloc(max_buffer_size, sizeof(char));
active_socket->wsaBuffer.len = max_buffer_size;
}
@ -645,7 +652,11 @@ static void *tnet_transport_thread(void *param)
}
else
{
TSK_DEBUG_INFO("WSARecv(%d bytes) success on [%s]", active_socket->readCount, transport->description);
//TSK_DEBUG_INFO("WSARecv(%d bytes) success on [%s]\n%s\n", active_socket->readCount, transport->description, active_socket->wsaBuffer.buf);
if(active_socket->callback)
{
active_socket->callback(active_socket->fd, active_socket->wsaBuffer.buf, active_socket->readCount);
}
}
}
@ -665,35 +676,40 @@ static void *tnet_transport_thread(void *param)
}
/*{
int test = 10;
WSAOVERLAPPED RecvOverlapped = {0};
RecvOverlapped.hEvent = active_event;
//* Create socket's internal buffer.
if(!active_socket->wsaBuffer.buf)
{
size_t max_buffer_size = TNET_SOCKET_TYPE_IS_DGRAM(transport->server->type) ? DGRAM_MAX_SIZE : STREAM_MAX_SIZE;
size_t max_buffer_size = TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) ? DGRAM_MAX_SIZE : STREAM_MAX_SIZE;
active_socket->wsaBuffer.buf = tsk_calloc(max_buffer_size, sizeof(char));
active_socket->wsaBuffer.len = max_buffer_size;
}
//* Receive the waiting data.
if(WSARecv(active_socket->fd, &(active_socket->wsaBuffer), 1, &(active_socket->readCount), &flags, &RecvOverlapped, NULL) == SOCKET_ERROR)
while(test--)
{
if(WSAGetLastError() == WSAEWOULDBLOCK)
//* Receive the waiting data.
if(WSARecv(active_socket->fd, &(active_socket->wsaBuffer), 1, &(active_socket->readCount), &flags, &RecvOverlapped, NULL) == SOCKET_ERROR)
{
TSK_DEBUG_INFO("WSAEWOULDBLOCK error for READ operation");
if(WSAGetLastError() == WSAEWOULDBLOCK)
{
TSK_DEBUG_INFO("WSAEWOULDBLOCK error for READ operation");
}
else
{
tnet_socket_desc_remove(index, context);
TNET_PRINT_LAST_ERROR();
//continue;
}
}
else
{
tnet_socket_desc_remove(index, context);
TNET_PRINT_LAST_ERROR();
//continue;
}
TSK_DEBUG_INFO("WSARecv(%d bytes) success on [%s]", active_socket->readCount, transport->description);
}
else
{
TSK_DEBUG_INFO("WSARecv(%d bytes) success on [%s]", active_socket->readCount, transport->description);
}
//ret = WSAGetOverlappedResult(active_socket->fd, &RecvOverlapped, &active_socket->readCount, FALSE, &flags);

View File

@ -37,20 +37,19 @@
typedef void tnet_transport_handle_t;
TINYNET_API tnet_transport_handle_t* tnet_transport_start(const char* host, uint16_t port, tnet_socket_type_t type, const char* description);
TINYNET_API int tnet_transport_get_isconnected(const tnet_transport_handle_t *handle);
TINYNET_API const char* tnet_transport_get_description(const tnet_transport_handle_t *handle);
TINYNET_API uint16_t tnet_transport_get_local_port(const tnet_transport_handle_t *handle, int client);
#define tnet_transport_get_tport(handle) tnet_transport_get_local_port(handle, 1)
#define tnet_transport_get_server_port(handle) tnet_transport_get_local_port(handle, 0)
TINYNET_API const char* tnet_transport_get_local_ip(const tnet_transport_handle_t *handle, int client);
#define tnet_transport_get_tip(handle) tnet_transport_get_local_ip(handle, 1)
#define tnet_transport_get_server_ip(handle) tnet_transport_get_local_ip(handle, 0)
typedef int (*tnet_transport_data_read)(tnet_fd_t fd, const void* data, size_t size);
TINYNET_API int tnet_transport_add_socket(const tnet_transport_handle_t *handle, int32_t fd);
TINYNET_API int tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, uint16_t port);
TINYNET_API int tnet_transport_send(const tnet_transport_handle_t *handle, const void* buf, size_t size);
TINYNET_API int tnet_transport_sendto(const tnet_transport_handle_t *handle, const struct sockaddr *to, const void* buf, size_t size);
TINYNET_API tnet_transport_handle_t* tnet_transport_start(const char* host, tnet_port_t port, tnet_socket_type_t type, const char* description);
TINYNET_API int tnet_transport_isrunning(const tnet_transport_handle_t *handle);
TINYNET_API const char* tnet_transport_get_description(const tnet_transport_handle_t *handle);
TINYNET_API int tnet_transport_get_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd);
TINYNET_API tnet_fd_t tnet_transport_connectto(const tnet_transport_handle_t *handle, const char* host, tnet_port_t port);
TINYNET_API size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t from, const void* buf, size_t size);
TINYNET_API size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_t from, const struct sockaddr *to, const void* buf, size_t size);
TINYNET_API int tnet_transport_set_callback(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_transport_data_read callback);
TINYNET_API tnet_socket_type_t tnet_transport_get_socket_type(const tnet_transport_handle_t *handle);
TINYNET_API int tnet_transport_shutdown(tnet_transport_handle_t** handle);

View File

@ -32,6 +32,7 @@
#include "tsk_debug.h"
#include "tsk_string.h"
#include "tsk_memory.h"
#include "tnet_socket.h"
@ -74,7 +75,7 @@ void tnet_getlasterror(tnet_error_t *error)
/**
* @fn int32_t tnet_getaddrinfo(const char *node, const char *service,
* @fn int tnet_getaddrinfo(const char *node, const char *service,
* const struct addrinfo *hints, struct addrinfo **res)
*
* @brief converts human-readable text strings representing hostnames or IP addresses into a dynamically allocated linked list of struct addrinfo structures.
@ -90,7 +91,7 @@ void tnet_getlasterror(tnet_error_t *error)
*
* @return Success returns zero. Failure returns a nonzero error code.
**/
int32_t tnet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
int tnet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
{
return getaddrinfo(node, service, hints, res);
}
@ -110,7 +111,7 @@ void tnet_freeaddrinfo(struct addrinfo *ai)
freeaddrinfo(ai);
}
int tnet_getPort(int32_t fd, uint16_t *port)
int tnet_get_ip_n_port(tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port)
{
*port = 0;
@ -118,9 +119,6 @@ int tnet_getPort(int32_t fd, uint16_t *port)
{
int status;
struct sockaddr_storage ss;
//struct hostent *hp;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
socklen_t namelen = sizeof(ss);
if(status = getsockname(fd, (struct sockaddr*)&ss, &namelen))
{
@ -131,17 +129,35 @@ int tnet_getPort(int32_t fd, uint16_t *port)
{
case AF_INET:
{
sin = ((struct sockaddr_in*)&ss);
*port = ntohs(sin->sin_port);
//hp = gethostbyaddr(&(sin->sin_addr), sizeof(sin->sin_addr), ss.ss_family);
struct sockaddr_in *sin = ((struct sockaddr_in*)&ss);
if(port)
{
*port = ntohs(sin->sin_port);
}
if(ip)
{
if(status = tnet_getnameinfo((struct sockaddr*)sin, sizeof(*sin), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))
{
return status;
}
}
break;
}
case AF_INET6:
{
sin6 = ((struct sockaddr_in6*)&ss);
*port = ntohs(sin6->sin6_port);
//hp = gethostbyaddr(&(sin6->sin6_addr), sizeof(sin6->sin6_addr), ss.ss_family);
struct sockaddr_in6 *sin6 = ((struct sockaddr_in6*)&ss);
if(port)
{
*port = ntohs(sin6->sin6_port);
}
if(ip)
{
if(status = tnet_getnameinfo((struct sockaddr*)sin6, sizeof(*sin6), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))
{
return status;
}
}
break;
}
@ -163,14 +179,14 @@ int tnet_getnameinfo(const struct sockaddr *sa, socklen_t salen, char* node, soc
return getnameinfo(sa, salen, node, nodelen, service, servicelen, flags);
}
int tnet_gethostname(tnet_hostname_t* result)
int tnet_gethostname(tnet_host_t* result)
{
return gethostname(*result, sizeof(*result));
}
int tnet_sockaddr_init(const char *host, uint16_t port, tnet_socket_type_t type, struct sockaddr *addr)
int tnet_sockaddrinfo_init(const char *host, tnet_port_t port, enum tnet_socket_type_e type, struct sockaddr_storage *ai_addr, int *ai_family, int *ai_socktype, int *ai_protocol)
{
int status;
int status = 0;
struct addrinfo *result = 0;
struct addrinfo *ptr = 0;
struct addrinfo hints;
@ -197,7 +213,20 @@ int tnet_sockaddr_init(const char *host, uint16_t port, tnet_socket_type_t type,
{
if(ptr->ai_family == hints.ai_family && ptr->ai_socktype == hints.ai_socktype && ptr->ai_protocol == hints.ai_protocol)
{
memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
/* duplicate addrinfo ==> Bad idea
*ai = tsk_calloc(1, sizeof (struct addrinfo));
memcpy (*ai, ptr, sizeof (struct addrinfo));
(*ai)->ai_addr = tsk_calloc(1, ptr->ai_addrlen);
memcpy((*ai)->ai_addr, ptr->ai_addr, ptr->ai_addrlen);
(*ai)->ai_addrlen = ptr->ai_addrlen;
(*ai)->ai_next = 0;
(*ai)->ai_canonname = 0;*/
if(ai_addr)memcpy(ai_addr, ptr->ai_addr, ptr->ai_addrlen);
if(ai_family) *ai_family = ptr->ai_family;
if(ai_socktype) *ai_socktype = ptr->ai_socktype;
if(ai_protocol) *ai_protocol = ptr->ai_protocol;
break;
}
}
@ -206,4 +235,62 @@ bail:
tnet_freeaddrinfo(result);
return status;
}
int tnet_sockaddr_init(const char *host, tnet_port_t port, tnet_socket_type_t type, struct sockaddr_storage *addr)
{
int status;
struct sockaddr_storage ai_addr;
if(status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, 0, 0, 0))
{
return status;
}
memcpy(addr, &ai_addr, sizeof(ai_addr));
return status;
}
int tnet_sockfd_init(const char *host, tnet_port_t port, enum tnet_socket_type_e type, tnet_fd_t *fd)
{
int status = -1;
struct sockaddr_storage ai_addr;
int ai_family, ai_socktype, ai_protocol;
*fd = INVALID_SOCKET;
if(status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, &ai_family, &ai_socktype, &ai_protocol))
{
goto bail;
}
if((*fd = socket(ai_family, ai_socktype, ai_protocol)) == INVALID_SOCKET)
{
TNET_PRINT_LAST_ERROR();
goto bail;
}
if(status = bind(*fd, (const struct sockaddr*)&ai_addr, sizeof(ai_addr)))
{
TNET_PRINT_LAST_ERROR();
tnet_sockfd_close(fd);
goto bail;
}
bail:
return (*fd == INVALID_SOCKET) ? status : 0;
}
int tnet_sockfd_close(tnet_fd_t *fd)
{
int ret;
#if TNET_UNDER_WINDOWS
ret = closesocket(*fd);
#else
ret = close(*fd);
#endif
*fd = INVALID_SOCKET;
return ret;
}

View File

@ -43,7 +43,11 @@
# include <netdb.h>
#endif
typedef char tnet_hostname_t[/*NI_MAXHOST*/255];
typedef int32_t tnet_fd_t;
typedef uint16_t tnet_port_t;
typedef char tnet_host_t[NI_MAXHOST];
typedef char tnet_ip_t[INET6_ADDRSTRLEN];
#ifdef _WIN32_WCE
typedef TCHAR tnet_error_t[512];
#else
@ -52,14 +56,20 @@ typedef char tnet_error_t[512];
TINYNET_API void tnet_getlasterror(tnet_error_t *error);
TINYNET_API int32_t tnet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
TINYNET_API int tnet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
TINYNET_API void tnet_freeaddrinfo(struct addrinfo *ai);
TINYNET_API int tnet_getPort(int32_t fd, uint16_t *port);
TINYNET_API int tnet_get_ip_n_port(tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port);
#define tnet_get_ip(fd, ip) tnet_get_ip_n_port(fd, ip, 0)
#define tnet_get_port(fd, port) tnet_get_ip_n_port(fd, 0, port)
TINYNET_API int tnet_getnameinfo(const struct sockaddr *sa, socklen_t salen, char* node, socklen_t nodelen, char* service, socklen_t servicelen, int flags);
TINYNET_API int tnet_gethostname(tnet_hostname_t* result);
TINYNET_API int tnet_gethostname(tnet_host_t* result);
TINYNET_API int tnet_sockaddr_init(const char *host, uint16_t port, enum tnet_socket_type_e type, struct sockaddr *addr);
TINYNET_API int tnet_sockaddrinfo_init(const char *host, tnet_port_t port, enum tnet_socket_type_e type, struct sockaddr_storage *ai_addr, int *ai_family, int *ai_socktype, int *ai_protocol);
TINYNET_API int tnet_sockaddr_init(const char *host, tnet_port_t port, enum tnet_socket_type_e type, struct sockaddr_storage *addr);
TINYNET_API int tnet_sockfd_init(const char *host, tnet_port_t port, enum tnet_socket_type_e type, tnet_fd_t *fd);
TINYNET_API int tnet_sockfd_close(tnet_fd_t *fd);
#define TNET_PRINT_LAST_ERROR() \
{ \

View File

@ -24,7 +24,7 @@
void test_sockets()
{
tnet_socket_tcp_t * tcp_socket = TNET_SOCKET_CREATE("", 0, tnet_socket_type_udp_ipv6);
tnet_socket_tcp_t * tcp_socket = TNET_SOCKET_CREATE(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6);
int test = 0;
if(!TNET_SOCKET_IS_VALID(tcp_socket))

View File

@ -21,51 +21,74 @@
*/
#ifndef TNET_TEST_TRANSPORT_H
#define TNET_TEST_TRANSPORT_H
#define REMOTE_IPV4 "192.168.0.15"
#define SIP_MESSAGE \
"REGISTER sip:wonderland.net SIP/2.0\r\n" \
"Via: SIP/2.0/UDP %s:%d;comp=sigcomp;rport;branch=z9hG4bK1245420841406\r\n" \
"From: \"Mamadou\" <sip:mamadou@wonderland.net>;tag=29358\r\n" \
"To: <sip:mamadou@wonderland.net>;tag= 12345\r\n" \
"REGISTER sip:micromethod.com SIP/2.0\r\n" \
"Via: SIP/2.0/%s %s:%d;rport;branch=z9hG4bK1245420841406%d\r\n" \
"From: <sip:mamadou@micromethod.com>;tag=29358\r\n" \
"To: <sip:mamadou@micromethod.com>\r\n" \
"Call-ID: M-fa53180346f7f55ceb8d8670f9223dbb\r\n" \
"CSeq: 201 REGISTER\r\n" \
"Max-Forwards: 70\r\n" \
"Contact: <sip:mamadou@%s:%d;comp=sigcomp;transport=%s>\r\n" \
"Expires: 600\r\n" \
"Contact: <sip:mamadou@%s:%d;transport=%s>\r\n" \
"Expires: 20\r\n" \
"\r\n"
static int tnet_tcp_data_read(tnet_fd_t fd, const void* data, size_t size)
{
/* Do quick job. */
TSK_DEBUG_INFO("--- UDP ---\n%s\n", data);
return 0;
}
static int tnet_udp_data_read(tnet_fd_t fd, const void* data, size_t size)
{
/* Do quick job. */
TSK_DEBUG_INFO("--- UDP ---\n%s\n", data);
return 0;
}
void test_transport_tcp_ipv4()
{
tnet_socket_type_t type = tnet_socket_type_tcp_ipv4;
tnet_transport_handle_t *transport = tnet_transport_start(0, 0, type, "TCP/IPV4 TRANSPORT");
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = INVALID_SOCKET;
tnet_transport_handle_t *transport = tnet_transport_start(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, type, "TCP/IPV4 TRANSPORT");
if(!transport)
{
TSK_DEBUG_ERROR("Failed to create TCP/IPv4 transport.");
return;
}
tsk_thread_sleep(1000);
//tsk_thread_sleep(500);
if(tnet_transport_connectto(transport, REMOTE_IPV4, 5060))
/* Connect to the SIP Registrar */
if((fd = tnet_transport_connectto(transport, REMOTE_IPV4, 5060)) == INVALID_SOCKET)
{
TSK_DEBUG_ERROR("Failed to connect TCP/IPv4 transport.");
tnet_transport_shutdown(&transport);
return;
}
while(!tnet_transport_get_isconnected(transport))
/* Set our callback function */
tnet_transport_set_callback(transport, fd, tnet_tcp_data_read);
//while(!tnet_transport_get_isconnected(transport))
{
/* Connecto succeed but not connected yet.*/
tsk_thread_sleep(2000);
tsk_thread_sleep(500);
}
/* Send our SIP message */
{
char* message = 0;
const char* ip =tnet_transport_get_tip(transport);
uint16_t port = tnet_transport_get_tport(transport);
tsk_sprintf(&message, SIP_MESSAGE, ip, port, ip, port, "tcp");
if(tnet_transport_send(transport, message, strlen(message)))
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, SIP_MESSAGE, "TCP", ip, port, port, ip, port, "tcp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using TCP/IPv4 transport.");
tnet_transport_shutdown(&transport);
@ -80,25 +103,41 @@ void test_transport_tcp_ipv4()
void test_transport_udp_ipv4()
{
tnet_socket_type_t type = tnet_socket_type_udp_ipv4;
tnet_transport_handle_t *transport = tnet_transport_start(0, 0, type, "UDP/IPV4 TRANSPORT");
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = INVALID_SOCKET;
tnet_transport_handle_t *transport = tnet_transport_start(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, type, "UDP/IPV4 TRANSPORT");
if(!transport)
{
TSK_DEBUG_ERROR("Failed to create UDP/IPv4 transport.");
return;
}
tsk_thread_sleep(1000);
//tsk_thread_sleep(2000);
/* Connect to our SIP REGISTRAR */
if((fd = tnet_transport_connectto(transport, REMOTE_IPV4, 5060)) == INVALID_SOCKET)
{
TSK_DEBUG_ERROR("Failed to connect UDP/IPv4 transport.");
tnet_transport_shutdown(&transport);
return;
}
//tsk_thread_sleep(2000);
/* Set our callback function */
tnet_transport_set_callback(transport, fd, tnet_udp_data_read);
/* Send our SIP message */
{
struct sockaddr addr;
char* message = 0;
const char* ip =tnet_transport_get_tip(transport);
uint16_t port = tnet_transport_get_tport(transport);
tsk_sprintf(&message, SIP_MESSAGE, ip, port, ip, port, "udp");
tnet_sockaddr_init(REMOTE_IPV4, 5060, type, &addr);
if(tnet_transport_sendto(transport, &addr, message, strlen(message)))
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, SIP_MESSAGE, "UDP", ip, port, port, ip, port, "udp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using TCP/IPv4 transport.");
TSK_DEBUG_ERROR("Failed to send data using UDP/IPv4 transport.");
tnet_transport_shutdown(&transport);
TSK_FREE(message);
return;

View File

@ -39,6 +39,8 @@
#include "tsk_url.h"
#include "tsk_params.h"
#include "tsk_time.h"
#include "tsk_timer.h"
#include "tsk_condwait.h"
#include "tsk_mutex.h"

View File

@ -33,16 +33,23 @@
#include "tsk_debug.h"
#include "tsk_macros.h"
#include "tsk_time.h"
#include <pthread.h>
#include <time.h>
#if TSK_UNDER_WINDOWS
#include <windows.h>
#else
#include <sys/time.h>
# include <windows.h>
# include "tsk_errno.h"
typedef HANDLE CONDWAIT_T;
# define TIMED_OUT WAIT_TIMEOUT
#else
# include <sys/time.h>
# include <pthread.h>
typedef pthread_cond_t* CONDWAIT_T;
# define TIMED_OUT ETIMEDOUT
#endif
/**@defgroup tsk_condwait_group Pthread CondWait
*/
@ -50,8 +57,10 @@
*/
typedef struct tsk_condwait_s
{
pthread_cond_t* pcond; /**< Handle pointing to the condwait */
CONDWAIT_T pcond; /**< Handle pointing to the condwait */
#if !TSK_UNDER_WINDOWS
tsk_mutex_handle_t* mutex; /**< Locker*/
#endif
}
tsk_condwait_t;
@ -63,22 +72,33 @@ tsk_condwait_t;
tsk_condwait_handle_t* tsk_condwait_create()
{
tsk_condwait_t *condwait = tsk_calloc(1, sizeof(tsk_condwait_t));
if(condwait)
{
condwait->pcond = (pthread_cond_t*)tsk_calloc(1, sizeof(pthread_cond_t));
#if TSK_UNDER_WINDOWS
condwait->pcond = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!condwait->pcond)
{
TSK_FREE(condwait);
}
#else
condwait->pcond = (CONDWAIT_T)tsk_calloc(1, sizeof(CONDWAIT_T));
if(pthread_cond_init(condwait->pcond, 0))
{
TSK_DEBUG_ERROR("Failed to initialize the new conwait.");
}
if(!(condwait->mutex = tsk_mutex_create()))
{
if(!pthread_mutex_init((pthread_mutex_t*)condwait->mutex, 0))
{
TSK_DEBUG_ERROR("Failed to initialize the new mutex.");
}
pthread_cond_destroy(condwait->pcond);
TSK_FREE(condwait);
TSK_DEBUG_ERROR("Failed to initialize the internal mutex.");
}
#endif
}
else
if(!condwait)
{
TSK_DEBUG_ERROR("Failed to create new conwait.");
}
@ -96,6 +116,12 @@ int tsk_condwait_wait(tsk_condwait_handle_t* handle)
int ret = EINVAL;
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
#if TSK_UNDER_WINDOWS
if((ret = (WaitForSingleObject(condwait->pcond, INFINITE) == WAIT_FAILED) ? -1 : 0))
{
TSK_DEBUG_ERROR("WaitForSingleObject function failed: %d", ret);
}
#else
if(condwait && condwait->mutex)
{
tsk_mutex_lock(condwait->mutex);
@ -105,6 +131,7 @@ int tsk_condwait_wait(tsk_condwait_handle_t* handle)
}
tsk_mutex_unlock(condwait->mutex);
}
#endif
return ret;
}
@ -117,9 +144,27 @@ int tsk_condwait_wait(tsk_condwait_handle_t* handle)
*/
int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
{
#if TSK_UNDER_WINDOWS
DWORD ret = WAIT_FAILED;
#else
int ret = EINVAL;
#endif
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
#if TSK_UNDER_WINDOWS
if((ret = WaitForSingleObject(condwait->pcond, (DWORD)ms)) != WAIT_OBJECT_0)
{
if(ret == TIMED_OUT)
{
TSK_DEBUG_INFO("WaitForSingleObject function timedout: %d", ret);
}
else
{
TSK_DEBUG_ERROR("WaitForSingleObject function failed: %d", ret);
}
return (ret == TIMED_OUT ? 0 : ret);
}
#else
if(condwait && condwait->mutex)
{
struct timespec ts = {0, 0};
@ -133,7 +178,7 @@ int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
tsk_mutex_lock(condwait->mutex);
if(ret = pthread_cond_timedwait(condwait->pcond, (pthread_mutex_t*)condwait->mutex, &ts))
{
if(ret == ETIMEDOUT)
if(ret == TIMED_OUT)
{
TSK_DEBUG_INFO("pthread_cond_timedwait function timedout: %d", ret);
}
@ -142,10 +187,13 @@ int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
TSK_DEBUG_ERROR("pthread_cond_timedwait function failed: %d", ret);
}
}
tsk_mutex_unlock(condwait->mutex);
return ret;
return (ret == TIMED_OUT ? 0 : ret);
}
#endif
return ret;
}
@ -160,32 +208,41 @@ int tsk_condwait_signal(tsk_condwait_handle_t* handle)
int ret = EINVAL;
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
#if TSK_UNDER_WINDOWS
if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1))
{
ret = GetLastError();
TSK_DEBUG_ERROR("SetEvent/ResetEvent function failed: %d", ret);
}
#else
if(condwait && condwait->mutex)
{
tsk_mutex_lock(condwait->mutex);
if(ret = pthread_cond_signal(condwait->pcond))
{
TSK_DEBUG_ERROR("pthread_cond_signal function failed: %d", ret);
}
tsk_mutex_unlock(condwait->mutex);
}
#endif
return ret;
}
/**@ingroup tsk_condwait_group
* Gets the internal mutex used by the CondWait object.
* @param handle The CondWait object holding the mutex.
* @retval The internal mutex.
*/
tsk_mutex_handle_t* tsk_condwait_get_mutex(tsk_condwait_handle_t* handle)
{
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
if(condwait)
{
return condwait->mutex;
}
return 0;
}
///**@ingroup tsk_condwait_group
//* Gets the internal mutex used by the CondWait object.
//* @param handle The CondWait object holding the mutex.
//* @retval The internal mutex.
//*/
//tsk_mutex_handle_t* tsk_condwait_get_mutex(tsk_condwait_handle_t* handle)
//{
// tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
// if(condwait)
// {
// return condwait->mutex;
// }
// return 0;
//}
/**@ingroup tsk_condwait_group
* Wakes up all threads that are currently waiting on @ref condwait variable.
@ -198,6 +255,13 @@ int tsk_condwait_broadcast(tsk_condwait_handle_t* handle)
int ret = EINVAL;
tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
#if TSK_UNDER_WINDOWS
if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1))
{
ret = GetLastError();
TSK_DEBUG_ERROR("SetEvent function failed: %d", ret);
}
#else
if(condwait && condwait->mutex)
{
tsk_mutex_lock(condwait->mutex);
@ -207,6 +271,8 @@ int tsk_condwait_broadcast(tsk_condwait_handle_t* handle)
}
tsk_mutex_unlock(condwait->mutex);
}
#endif
return ret;
}
@ -221,9 +287,13 @@ void tsk_condwait_destroy(tsk_condwait_handle_t** handle)
if(condwait && *condwait)
{
#if TSK_UNDER_WINDOWS
CloseHandle((*condwait)->pcond);
#else
tsk_mutex_destroy(&((*condwait)->mutex));
pthread_cond_destroy((*condwait)->pcond);
TSK_FREE((*condwait)->pcond);
#endif
tsk_free((void**)condwait);
}
else

View File

@ -43,7 +43,6 @@ TINYSAK_API int tsk_condwait_wait(tsk_condwait_handle_t* handle);
TINYSAK_API int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms);
TINYSAK_API int tsk_condwait_signal(tsk_condwait_handle_t* handle);
TINYSAK_API int tsk_condwait_broadcast(tsk_condwait_handle_t* handle);
TINYSAK_API tsk_mutex_handle_t* tsk_condwait_get_mutex(tsk_condwait_handle_t* handle);
TINYSAK_API void tsk_condwait_destroy(tsk_condwait_handle_t** handle);
#endif /* _TINYSAK_CONDWAIT_H_ */

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou@yahoo.fr>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tsk_mutex.h
* @brief ERRNO.
*
* @author Mamadou Diop <diopmamadou(at)yahoo.fr>
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#ifndef _TINYSAK_ERRNO_H_
#define _TINYSAK_ERRNO_H_
#include "tinySAK_config.h"
#ifndef _WIN32_WCE
# include <errno.h>
#else
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define EDOM 33
#define EDEADLK 36
#define ENAMETOOLONG 38
#define ENOLCK 39
#define ENOSYS 40
#define ENOTEMPTY 41
/* Error codes used in the Secure CRT functions */
#ifndef RC_INVOKED
#if !defined(_SECURECRT_ERRCODE_VALUES_DEFINED)
#define _SECURECRT_ERRCODE_VALUES_DEFINED
#define EINVAL 22
#define ERANGE 34
#define EILSEQ 42
#define STRUNCATE 80
#endif
#endif
#endif
#endif

View File

@ -254,13 +254,14 @@ void tsk_list_remove_item_by_pred(tsk_list_t* list, tsk_list_func_predicate pred
{
if(!predicate(curr, data))
{
if(prev == curr && curr->next == NULL)
{ /* There was only one item */
list->head = NULL;
if(prev == curr)
{
/* Found at first position. */
list->head = curr->next;
}
else prev->next = curr->next;
curr = tsk_object_unref(curr);
/*curr =*/ tsk_object_unref(curr);
break;
}

View File

@ -31,7 +31,14 @@
#include "tsk_memory.h"
#include "tsk_debug.h"
#include <pthread.h>
#if TSK_UNDER_WINDOWS
# include <windows.h>
# include "tsk_errno.h"
typedef HANDLE MUTEX_T;
#else
# include <pthread.h>
typedef pthread_mutex_t* MUTEX_T;
#endif
// FIXME: Momory leaks in mutex
@ -44,16 +51,20 @@
* @sa @ref tsk_mutex_destroy
*/
tsk_mutex_handle_t* tsk_mutex_create()
{
tsk_mutex_handle_t *handle = tsk_calloc(1, sizeof(pthread_mutex_t));
if(handle)
{
MUTEX_T handle = 0;
#if TSK_UNDER_WINDOWS
handle = CreateMutex(NULL, FALSE, NULL);
#else
handle = tsk_calloc(1, sizeof(MUTEX_T));
if(pthread_mutex_init((MUTEX_T)handle, 0))
{
if(pthread_mutex_init((pthread_mutex_t*)handle, 0))
{
TSK_DEBUG_ERROR("Failed to initialize the new mutex.");
}
TSK_FREE(handle);
}
else
#endif
if(!handle)
{
TSK_DEBUG_ERROR("Failed to create new mutex.");
}
@ -71,7 +82,11 @@ int tsk_mutex_lock(tsk_mutex_handle_t* handle)
int ret = EINVAL;
if(handle)
{
if(ret = pthread_mutex_lock((pthread_mutex_t*)handle))
#if TSK_UNDER_WINDOWS
if((ret = WaitForSingleObject((MUTEX_T)handle , INFINITE)) == WAIT_FAILED)
#else
if(ret = pthread_mutex_lock((MUTEX_T)handle))
#endif
{
TSK_DEBUG_ERROR("Failed to lock the mutex: %d", ret);
}
@ -90,7 +105,11 @@ int tsk_mutex_unlock(tsk_mutex_handle_t* handle)
int ret = EINVAL;
if(handle)
{
if(ret = pthread_mutex_unlock((pthread_mutex_t*)handle))
#if TSK_UNDER_WINDOWS
if((ret = ReleaseMutex((MUTEX_T)handle) ? 0 : -1))
#else
if(ret = pthread_mutex_unlock((MUTEX_T)handle))
#endif
{
if(ret == EPERM)
{
@ -114,8 +133,13 @@ void tsk_mutex_destroy(tsk_mutex_handle_t** handle)
{
if(handle && *handle)
{
pthread_mutex_destroy((pthread_mutex_t*)*handle);
#if TSK_UNDER_WINDOWS
CloseHandle((MUTEX_T)*handle);
*handle = 0;
#else
pthread_mutex_destroy((MUTEX_T)*handle);
tsk_free(handle);
#endif
}
else
{

View File

@ -31,8 +31,15 @@
#include "tsk_memory.h"
#include "tsk_debug.h"
#include <semaphore.h>
#include <pthread.h>
#if TSK_UNDER_WINDOWS
# include <windows.h>
# include "tsk_errno.h"
typedef HANDLE SEMAPHORE_T;
#else
# include <pthread.h>
# include <semaphore.h>
typedef sem_t* SEMAPHORE_T;
#endif
/**@defgroup tsk_semaphore_group Pthread Semaphore
*/
@ -44,19 +51,26 @@
*/
tsk_semaphore_handle_t* tsk_semaphore_create()
{
tsk_semaphore_handle_t *handle = tsk_calloc(1, sizeof(sem_t));
if(handle)
SEMAPHORE_T handle = 0;
#if TSK_UNDER_WINDOWS
handle = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
#else
handle = tsk_calloc(1, sizeof(SEMAPHORE_T));
if(sem_init((SEMAPHORE_T)handle, PTHREAD_PROCESS_PRIVATE, 0))
{
if(sem_init((sem_t*)handle, PTHREAD_PROCESS_PRIVATE, 0))
{
TSK_DEBUG_ERROR("Failed to initialize the new semaphore.");
}
TSK_FREE(handle);
TSK_DEBUG_ERROR("Failed to initialize the new semaphore.");
}
else
#endif
if(!handle)
{
TSK_DEBUG_ERROR("Failed to create new mutex.");
}
return handle;
}
/**@ingroup tsk_semaphore_group
@ -70,7 +84,11 @@ int tsk_semaphore_increment(tsk_semaphore_handle_t* handle)
int ret = EINVAL;
if(handle)
{
if(ret = sem_post((sem_t*)handle))
#if TSK_UNDER_WINDOWS
if((ret = ReleaseSemaphore((SEMAPHORE_T)handle, 1L, 0L) ? 0 : -1))
#else
if(ret = sem_post((SEMAPHORE_T)handle))
#endif
{
TSK_DEBUG_ERROR("sem_post function failed: %d", ret);
}
@ -89,15 +107,19 @@ int tsk_semaphore_decrement(tsk_semaphore_handle_t* handle)
int ret = EINVAL;
if(handle)
{
#if TSK_UNDER_WINDOWS
ret = (WaitForSingleObject((SEMAPHORE_T)handle, INFINITE) == WAIT_OBJECT_0 ? 0 : -1);
if(ret) TSK_DEBUG_ERROR("sem_wait function failed: %d", ret);
#else
do
{
ret = sem_wait((sem_t*)handle);
ret = sem_wait((SEMAPHORE_T)handle);
}
while ( errno == EINTR );
if(ret) TSK_DEBUG_ERROR("sem_wait function failed: %d", errno);
#endif
}
if(ret) TSK_DEBUG_ERROR("sem_wait function failed: %d", errno);
return ret;
}
@ -110,8 +132,13 @@ void tsk_semaphore_destroy(tsk_semaphore_handle_t** handle)
{
if(handle && *handle)
{
sem_destroy((sem_t*)*handle);
#if TSK_UNDER_WINDOWS
CloseHandle((SEMAPHORE_T)*handle);
*handle = 0;
#else
sem_destroy((SEMAPHORE_T)*handle);
tsk_free(handle);
#endif
}
else
{

View File

@ -247,7 +247,7 @@ void tsk_strquote(char **str)
{
char *result = 0;
tsk_sprintf(&result, "\"%s\"", *str);
tsk_free(str);
tsk_free((void**)str);
*str = result;
}
}
@ -309,11 +309,24 @@ static void* tsk_string_destroy(void * self)
return self;
}
static int tsk_string_cmp(const void *obj1, const void *obj2)
{
const tsk_string_t *s1 = obj1;
const tsk_string_t *s2 = obj2;
if(s1 && s2)
{
return tsk_stricmp(s1->value, s2->value);
}
else if(!s1 && !s2) return 0;
else return -1;
}
static const tsk_object_def_t tsk_string_def_s =
{
sizeof(tsk_string_t),
tsk_string_create,
tsk_string_destroy,
0,
tsk_string_cmp,
};
const void *tsk_string_def_t = &tsk_string_def_s;

View File

@ -30,10 +30,10 @@
#include "tsk_thread.h"
#include "tsk_memory.h"
#include <pthread.h>
#if TSK_UNDER_WINDOWS
# include <windows.h>
#else
# include <pthread.h>
#endif
/**@defgroup tsk_thread_group Useful functions for threading.
@ -62,8 +62,14 @@ void tsk_thread_sleep(uint64_t ms)
*/
int tsk_thread_create(void** tid, void *(*start) (void *), void *arg)
{
#if TSK_UNDER_WINDOWS
DWORD ThreadId;
*((HANDLE*)tid) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start, arg, 0, &ThreadId);
return *((HANDLE*)tid) ? 0 : -1;
#else
*tid = tsk_calloc(1, sizeof(pthread_t));
return pthread_create((pthread_t*)*tid, 0, start, arg);
#endif
}
/**@ingroup tsk_thread_group
@ -73,7 +79,11 @@ int tsk_thread_create(void** tid, void *(*start) (void *), void *arg)
*/
int tsk_thread_join(void** tid)
{
#if TSK_UNDER_WINDOWS
return (WaitForSingleObject(*((HANDLE*)tid), INFINITE) == WAIT_FAILED) ? -1 : 0;
#else
int ret = pthread_join(*((pthread_t*)*tid), 0);
tsk_free(tid);
return ret;
#endif
}

View File

@ -28,11 +28,15 @@
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#include "tsk_time.h"
#include <time.h>
#if TSK_UNDER_WINDOWS
#include <windows.h>
# include <windows.h>
#elif defined(__SYMBIAN32__)
# include <_timeval.h>
#endif
#include <time.h>
/**@defgroup tsk_time_group Useful datetime functions
*/
@ -122,4 +126,4 @@ uint64_t tsk_time_epoch()
gettimeofday(&tv, 0);
return (((uint64_t)tv.tv_sec)*thousand) + (((uint64_t)tv.tv_usec)/thousand);
}
}

View File

@ -37,13 +37,13 @@ struct timeval;
struct timezone;
#endif
int tsk_gettimeofday(struct timeval *tv, struct timezone *tz);
uint64_t tsk_time_epoch();
TINYSAK_API int tsk_gettimeofday(struct timeval *tv, struct timezone *tz);
TINYSAK_API uint64_t tsk_time_epoch();
/**
* Gets the number of milliseconds since the EPOCH.
*/
#define tsk_time_epoch tsk_time_now
#define tsk_time_now() tsk_time_epoch()
#ifdef _WIN32_WCE

View File

@ -32,60 +32,110 @@
#include "tsk_list.h"
#include "tsk_thread.h"
#include "tsk_condwait.h"
#include "tsk_semaphore.h"
#include "tsk_time.h"
/**@defgroup tsk_timer_group Timers Management
*/
#define TSK_TIMER_CREATE(timeout, callback, arg) tsk_object_new(tsk_timer_def_t, timeout, callback, arg)
#define TSK_TIMER_SAFE_FREE(self) tsk_object_unref(self), self = 0
#define TSK_TIMER_TIMEOUT(self) ((tsk_timer_t*)self)->timeout
#define TSK_TIMER_GET_FIRST() (tsk_manager_timers && tsk_manager_timers->head) ? (tsk_timer_t*)(((tsk_list_item_t*)(tsk_manager_timers->head))->data) : 0
typedef struct tsk_timer_s
{
TSK_DECLARE_OBJECT;
const void *arg; /**< Opaque data to return to the callback function. */
uint64_t timeout; /**< Number of milliseconds after which the callback function is called. */
tsk_timer_callback callback; /**< The callback function to after @ref timeout milliseconds. */
tsk_timer_id_t id; /**< Unique timer identifier. */
const void *arg; /**< Opaque data to return with the callback function. */
uint64_t timeout; /**< When the timer will timeout(as EPOCH time). */
tsk_timer_callback callback; /**< The callback function to call after @ref timeout milliseconds. */
}
tsk_timer_t;
typedef tsk_list_t tsk_timers_L_t;
/*== Global variables. */
static tsk_condwait_handle_t *tsk_manager_condwait = 0;
static tsk_mutex_handle_t *tsk_manager_mutex = 0;
static tsk_mutex_handle_t *tsk_manager_timers_mutex = 0;
static tsk_semaphore_handle_t *tsk_manager_semaphore = 0;
static int tsk_manager_running = 0;
static int tsk_manager_break = 0;
static tsk_timers_L_t *tsk_manager_timers = 0;
static void *tsk_manager_thread_id = 0;
/*== Definitions */
static void *tsk_timer_manager_loop(void *param);
static void *__tsk_timer_manager_loop(void *param);
static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id);
static void __tsk_timer_manager_raise(tsk_timer_t *timer);
/**@ingroup tsk_timer_group
* Start the timer manager.
*/
int tsk_timer_manager_start()
{
int err = -1;
if(!tsk_manager_running && !tsk_manager_condwait)
{
tsk_manager_timers = TSK_LIST_CREATE();
tsk_manager_semaphore = tsk_semaphore_create();
tsk_manager_condwait = tsk_condwait_create();
tsk_manager_mutex = tsk_condwait_get_mutex(tsk_manager_condwait);
tsk_manager_timers_mutex = tsk_mutex_create();
//tsk_mutex_lock(tsk_manager_mutex); /* First lock. */
tsk_manager_break = 0;
tsk_thread_create(&tsk_manager_thread_id, tsk_timer_manager_loop, 0);
if(err = tsk_thread_create(&tsk_manager_thread_id, __tsk_timer_manager_loop, 0))
{
tsk_semaphore_destroy(&tsk_manager_semaphore);
tsk_condwait_destroy(&tsk_manager_condwait);
tsk_mutex_destroy(&tsk_manager_timers_mutex);
tsk_object_unref(tsk_manager_timers);
TSK_DEBUG_FATAL("Failed to start timer manager: %d\n", err);
return err;
}
while(!tsk_manager_running) tsk_thread_sleep(500);
}
return 0;
return err;
}
#if defined(DEBUG) || defined(_DEBUG)
void tsk_timer_manager_debug()
{
if(tsk_manager_timers && tsk_manager_running)
{
int index = 0;
tsk_list_item_t *item = 0;
tsk_mutex_lock(tsk_manager_timers_mutex);
tsk_list_foreach(item, tsk_manager_timers)
{
tsk_timer_t* timer = item->data;
TSK_DEBUG_INFO("timer [%d]- %llu, %llu", timer->id, timer->timeout, tsk_time_epoch());
}
tsk_mutex_unlock(tsk_manager_timers_mutex);
}
}
#endif
int tsk_timer_manager_stop()
{
if(tsk_manager_running && tsk_manager_condwait)
{
tsk_manager_break = 1;
tsk_semaphore_increment(tsk_manager_semaphore);
tsk_condwait_broadcast(tsk_manager_condwait);
//tsk_mutex_unlock(tsk_manager_mutex);
tsk_thread_join(&tsk_manager_thread_id);
tsk_semaphore_destroy(&tsk_manager_semaphore);
tsk_condwait_destroy(&tsk_manager_condwait);
tsk_mutex_destroy(&tsk_manager_timers_mutex);
tsk_object_unref(tsk_manager_timers);
tsk_manager_running = 0;
}
return 0;
@ -93,31 +143,191 @@ int tsk_timer_manager_stop()
tsk_timer_id_t tsk_timer_manager_schedule(uint64_t timeout, tsk_timer_callback callback, const void *arg)
{
return 0;
tsk_timer_id_t timer_id = INVALID_TIMER_ID;
if(tsk_manager_timers && tsk_manager_running)
{
tsk_timer_t *timer;
timer = TSK_TIMER_CREATE(timeout, callback, arg);
timer_id = timer->id;
tsk_mutex_lock(tsk_manager_timers_mutex);
tsk_list_push_ascending_data(tsk_manager_timers, ((void**) &timer));
tsk_mutex_unlock(tsk_manager_timers_mutex);
tsk_semaphore_increment(tsk_manager_semaphore);
tsk_condwait_broadcast(tsk_manager_condwait);
}
return timer_id;
}
void tsk_timer_manager_cancel(tsk_timer_id_t id)
int tsk_timer_manager_cancel(tsk_timer_id_t id)
{
int ret = -1;
if(tsk_manager_timers && tsk_manager_running)
{
const tsk_list_item_t *item;
tsk_mutex_lock(tsk_manager_timers_mutex);
item = tsk_list_find_item_by_pred(tsk_manager_timers, __tsk_pred_find_timer_by_id, &id);
if(item && item->data)
{
tsk_timer_t *timer = item->data;
timer->callback(timer->arg, tsk_canceled);
tsk_list_remove_item(tsk_manager_timers, (tsk_list_item_t*)item);
ret = 0;
}
tsk_mutex_unlock(tsk_manager_timers_mutex);
}
return ret;
}
static void *tsk_timer_manager_loop(void *param)
static void __tsk_timer_manager_raise(tsk_timer_t *timer)
{
if(tsk_manager_timers && tsk_manager_running)
{
if(timer)
{
if(timer->callback)
{
timer->callback(timer->arg, tsk_timedout);
}
tsk_mutex_lock(tsk_manager_timers_mutex);
tsk_list_remove_item_by_pred(tsk_manager_timers, __tsk_pred_find_timer_by_id, &(timer->id));
tsk_mutex_unlock(tsk_manager_timers_mutex);
}
}
}
static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id)
{
if(item && item->data)
{
tsk_timer_t *timer = item->data;
return (int)(timer->id - *((tsk_timer_id_t*)id));
}
return -1;
}
static void *__tsk_timer_manager_loop(void *param)
{
static tsk_timer_t *curr;
static uint64_t epoch;
TSK_DEBUG_INFO("TIMER MANAGER -- START");
tsk_manager_running = 1;
for(;;)
{
//tsk_mutex_lock(tsk_manager_mutex);
//tsk_condwait_wait(tsk_manager_condwait);
tsk_semaphore_decrement(tsk_manager_semaphore);
peek_first:
if(tsk_manager_break)
{
break;
}
tsk_mutex_lock(tsk_manager_timers_mutex);
curr = TSK_TIMER_GET_FIRST();
tsk_mutex_unlock(tsk_manager_timers_mutex);
if(curr)
{
epoch = tsk_time_epoch();
if(epoch >= curr->timeout)
{
__tsk_timer_manager_raise(curr);
}
else
{
if(tsk_condwait_timedwait(tsk_manager_condwait, (curr->timeout - epoch)))
{
break;
}
else
{
goto peek_first;
}
}
}
}
TSK_DEBUG_INFO("TIMER MANAGER -- STOP");
tsk_manager_running = 0;
return 0;
}
}
//========================================================
// Timer object definition
//
static void* tsk_timer_create(void * self, va_list * app)
{
static tsk_timer_id_t tsk_unique_timer_id = 1;
tsk_timer_t *timer = self;
if(timer)
{
timer->id = tsk_unique_timer_id++;
timer->timeout = va_arg(*app, uint64_t);
timer->callback = va_arg(*app, tsk_timer_callback);
timer->arg = va_arg(*app, const void *);
timer->timeout += tsk_time_epoch();
}
return self;
}
static void* tsk_timer_destroy(void * self)
{
tsk_timer_t *timer = self;
if(timer)
{
}
return self;
}
static int tsk_timer_cmp(const void *obj1, const void *obj2)
{
const tsk_timer_t *t1 = obj1;
const tsk_timer_t *t2 = obj2;
if(t1 && t2)
{
return (int)(t1->timeout - t2->timeout);
}
else if(!t1 && !t2) return 0;
else return -1;
}
static const tsk_object_def_t tsk_timer_def_s =
{
sizeof(tsk_timer_t),
tsk_timer_create,
tsk_timer_destroy,
tsk_timer_cmp,
};
const void * tsk_timer_def_t = &tsk_timer_def_s;

View File

@ -32,22 +32,29 @@
#include "tinySAK_config.h"
#define INVALID_TIMER_ID 0
#define TSK_TIMER_ID_IS_VALID(id) (id != INVALID_TIMER_ID)
typedef enum tsk_timer_retcode_e
{
tsk_error,
tsk_stopped,
tsk_canceled,
tsk_timedout,
}
tsk_timer_retcode_t;
typedef uint64_t tsk_timer_id_t;
typedef void (*tsk_timer_callback)(const void* arg, tsk_timer_retcode_t code);
typedef int (*tsk_timer_callback)(const void* arg, tsk_timer_retcode_t code);
TINYSAK_API int tsk_timer_manager_start();
TINYSAK_API int tsk_timer_manager_stop();
#if defined(DEBUG) || defined(_DEBUG)
TINYSAK_API void tsk_timer_manager_debug();
#endif
TINYSAK_API tsk_timer_id_t tsk_timer_manager_schedule(uint64_t timeout, tsk_timer_callback callback, const void *arg);
TINYSAK_API void tsk_timer_manager_cancel(tsk_timer_id_t id);
TINYSAK_API int tsk_timer_manager_cancel(tsk_timer_id_t id);
TINYSAK_API const void *tsk_timer_def_t;

View File

@ -27,6 +27,9 @@
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#if HAVE_LIBXML2_H
#include "tsk_xml.h"
#include "tsk_string.h"
#include "tsk_memory.h"
@ -289,3 +292,4 @@ xmlNodePtr tsk_xml_select_node(const xmlNodePtr root, ...)
return node;
}
#endif /* HAVE_LIBXML2_H */

View File

@ -33,6 +33,8 @@
#include "tinySAK_config.h"
#include "tsk_heap.h"
#include "tsk_list.h"
#if HAVE_LIBXML2_H
#include <libxml/tree.h>
#define TSK_XML_NODE_IS_TEXTVALUE(node) (node && node->type==XML_TEXT_NODE)
@ -168,4 +170,6 @@ TINYSAK_API const void *tsk_xml_namespace_def_t;
TINYSAK_API const void *tsk_xml_attribute_def_t;
TINYSAK_API const void *tsk_xml_element_def_t;
#endif /* HAVE_LIBXML2_H */
#endif /* _TINYSAK_XML_H_ */

View File

@ -12,6 +12,9 @@
<Platform
Name="Win32"
/>
<Platform
Name="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
@ -41,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\win32\include\pthread&quot;;&quot;$(DOUBANGO_HOME)\thirdparties\win32\include&quot;;&quot;$(SolutionDir)src&quot;"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\win32\include&quot;;&quot;$(SolutionDir)src&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -63,7 +66,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\tinySAK.lib &quot;$(DOUBANGO_HOME)\thirdparties\win32\lib\pthread\pthread.lib&quot;"
AdditionalDependencies="$(OutDir)\tinySAK.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
@ -166,6 +169,169 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
OutputDirectory="&quot;$(SolutionDir)$(ConfigurationName)\wce&quot;"
IntermediateDirectory="&quot;$(SolutionDir)$(ConfigurationName)&quot;"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="1"
/>
<Tool
Name="VCCLCompilerTool"
ExecutionBucket="7"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\wince\include&quot;;&quot;$(SolutionDir)src&quot;"
PreprocessorDefinitions="_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;$(ARCHFAM);$(_ARCHFAM_);_CONSOLE"
MinimalRebuild="true"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="true"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(OutDir)\tinySAK.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="8"
EntryPointSymbol="mainWCRTStartup"
TargetMachine="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCCodeSignTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
<DeploymentTool
ForceDirty="-1"
RemoteDirectory=""
RegisterOutput="0"
AdditionalFiles=""
/>
<DebuggerTool
/>
</Configuration>
<Configuration
Name="Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
OutputDirectory="$(SolutionDir)Windows Mobile 5.0 Pocket PC SDK (ARMV4I)\$(ConfigurationName)"
IntermediateDirectory="Windows Mobile 5.0 Pocket PC SDK (ARMV4I)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="1"
/>
<Tool
Name="VCCLCompilerTool"
ExecutionBucket="7"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
WarnAsError="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="0"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCCodeSignTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
<DeploymentTool
ForceDirty="-1"
RemoteDirectory=""
RegisterOutput="0"
AdditionalFiles=""
/>
<DebuggerTool
/>
</Configuration>
</Configurations>
<References>
</References>

View File

@ -30,22 +30,16 @@
#ifndef _TEST_MUTEX_H_
#define _TEST_MUTEX_H_
int mutex_testing = 0;
int mutex_threa_started = 0;
int mutex_thread_started = 0;
void *threadfunc_mutex(void *parm)
{
tsk_mutex_handle_t *mutex = (tsk_mutex_handle_t *)parm;
int ret = 0;
mutex_thread_started = 1;
ret = tsk_mutex_lock(mutex);
while(mutex_testing)
{
mutex_threa_started = 1;
tsk_mutex_lock(mutex);
}
printf("threadfunc_mutex/// %d\n", ret);
printf("threadfunc_mutex/// unlocked %d\n", ret);
return 0;
}
@ -59,14 +53,20 @@ void test_mutex()
printf("test_mutex//\n");
mutex_testing = 1;
tsk_mutex_lock(mutex);
tsk_thread_create(&tid[0], threadfunc_mutex, mutex);
while(!mutex_threa_started);
while(!mutex_thread_started) tsk_thread_sleep(1000);
mutex_testing = 0;
printf("test_mutex// threadfunc_mutex is locked for 1 second\n");
tsk_thread_sleep(1000);
printf("test_mutex// Now unlock threadfunc_mutex\n");
tsk_mutex_unlock(mutex);
tsk_thread_join(&(tid[0]));
tsk_mutex_destroy(&mutex);

View File

@ -53,16 +53,13 @@ void test_semaphore()
{
tsk_semaphore_handle_t *semaphore = tsk_semaphore_create();
void* tid[2] = {0,0};
int i;
printf("test_semaphore//\n");
tsk_thread_create(&tid[0], threadfunc_semaphore1, semaphore);
tsk_thread_create(&tid[1], threadfunc_semaphore2, semaphore);
/* VERY BAD */
while(sema_count<2);
for(i=0;i<10000000;i++);
tsk_thread_sleep(1000);
assert(!tsk_semaphore_increment(semaphore));
assert(!tsk_semaphore_increment(semaphore));

View File

@ -21,16 +21,56 @@
*/
#ifndef _TEST_TIMER_H_
#define _TEST_TIMER_H_
typedef struct test_timer_s
{
tsk_timer_id_t id;
uint64_t timeout;
const char *arg;
}
test_timer_t;
test_timer_t timers[] =
{
{0, 2000, "3"},
{1, 2500, "4"},
{2, 500, "1"},
{3, 1000, "2"},
{4, 1000, "2"},
{5, 0, "0"},
{6, 10000, "6"},
{7, 3000, "5"},
{8, 2500, "4"},
};
static int test_timer_callback(const void* arg, tsk_timer_retcode_t code)
{
// Do quick job
printf("test_timer - code=%d and arg=%s//\n", code, arg);
return 0;
}
void test_timer()
{
size_t i;
printf("test_timer//\n");
tsk_timer_manager_start();
tsk_timer_manager_schedule(100000, 0, 0);
for(i=0; i<sizeof(timers)/sizeof(test_timer_t); ++i)
{
timers[i].id = tsk_timer_manager_schedule(timers[i].timeout, test_timer_callback, timers[i].arg);
}
//tsk_timer_manager_cancel(timers[5].id);
tsk_timer_manager_cancel(timers[6].id);
tsk_timer_manager_cancel(timers[2].id);
//tsk_timer_manager_stop();
//tsk_timer_manager_debug();
tsk_thread_sleep(3020);
tsk_timer_manager_stop();
}
#endif /* _TEST_TIMER_H_ */
#endif /* _TEST_TIMER_H_ */

View File

@ -8,17 +8,31 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
Release|Win32 = Release|Win32
Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.ActiveCfg = Debug|Win32
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.Build.0 = Debug|Win32
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.ActiveCfg = Release|Win32
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.Build.0 = Release|Win32
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Win32.ActiveCfg = Debug|Win32
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Win32.Build.0 = Debug|Win32
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Win32.ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Win32.Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Release|Win32.ActiveCfg = Release|Win32
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Release|Win32.Build.0 = Release|Win32
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
{7A1F8D56-A91F-4658-867F-5E24837071C0}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -44,7 +44,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\win32\include&quot;;&quot;$(DOUBANGO_HOME)\thirdparties\win32\include\pthread&quot;"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\win32\include&quot;"
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;WIN32;_DEBUG;_WINDOWS;_USRDLL;TINYSAK_EXPORTS;_WIN32_WINNT 0x0501"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -66,7 +66,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="&quot;$(DOUBANGO_HOME)\thirdparties\win32\lib\libxml\vs_libxml2.dll.a&quot; &quot;$(DOUBANGO_HOME)\thirdparties\win32\lib\pthread\pthread.lib&quot; $(NOINHERIT)"
AdditionalDependencies="$(NOINHERIT)"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
@ -120,7 +120,7 @@
<Tool
Name="VCCLCompilerTool"
ExecutionBucket="7"
AdditionalIncludeDirectories="&quot;$(DOUBANGO_HOME)\thirdparties\wince\include&quot;;&quot;$(DOUBANGO_HOME)\thirdparties\wince\include\pthread&quot;;&quot;$(DOUBANGO_HOME)\thirdparties\wince\include\wcecompat&quot;"
AdditionalIncludeDirectories="$(DOUBANGO_HOME)\thirdparties\wince\include"
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;TINYSAK_EXPORTS;_DEBUG;_WIN32_WCE=$(CEVER);UNDER_CE;$(PLATFORMDEFINES);WINCE;DEBUG;_WINDOWS;_USRDLL;$(ARCHFAM);$(_ARCHFAM_)"
MinimalRebuild="true"
ExceptionHandling="0"
@ -143,7 +143,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions=" /subsystem:windowsce,5.01 /machine:THUMB"
AdditionalDependencies="ws2.lib &quot;$(DOUBANGO_HOME)\thirdparties\wince\lib\libxml\libxml2.lib&quot; &quot;$(DOUBANGO_HOME)\thirdparties\wince\lib\pthread\pthread.lib&quot; &quot;$(DOUBANGO_HOME)\thirdparties\wince\lib\wcecompat\wcecompat.lib&quot;"
AdditionalDependencies="ws2.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="8"
@ -366,6 +366,10 @@
RelativePath=".\src\tsk_debug.h"
>
</File>
<File
RelativePath=".\src\tsk_errno.h"
>
</File>
<File
RelativePath=".\src\tsk_heap.h"
>

View File

@ -303,7 +303,7 @@ void tcomp_compartment_addState(tcomp_compartment_t *compartment, tcomp_state_t
tcomp_state_makeValid(*lpState);
compartment->total_memory_left -= TCOMP_GET_STATE_SIZE(*lpState);
tsk_list_add_data(compartment->local_states, ((void**) lpState));
tsk_list_push_back_data(compartment->local_states, ((void**) lpState));
TSK_DEBUG_INFO("SigComp - Add new state.");
*lpState = 0;
@ -398,7 +398,7 @@ void tcomp_compartment_addNack(tcomp_compartment_t *compartment, const uint8_t n
id = _TCOMP_BUFFER_CREATE(nackId, TSK_SHA1HashSize);
tsk_list_add_data(compartment->nacks, ((void**) &id));
tsk_list_push_back_data(compartment->nacks, ((void**) &id));
compartment->nacks_history_count++;
tsk_safeobj_unlock(compartment);

View File

@ -245,7 +245,7 @@ int tcomp_decompressordisp_appendStream(tcomp_decompressordisp_t *dispatcher, co
{
lpBuffer = newbuf;
lpBuffer->buffer = TCOMP_BUFFER_CREATE();
tsk_list_add_data(dispatcher->streamBuffers, ((void**) &newbuf));
tsk_list_push_back_data(dispatcher->streamBuffers, ((void**) &newbuf));
}
else
{

View File

@ -73,7 +73,7 @@ tcomp_compartment_t *tcomp_statehandler_getCompartment(const tcomp_statehandler_
{
newcomp = TCOMP_COMPARTMENT_CREATE(id, tcomp_params_getParameters(statehandler->sigcomp_parameters));
result = newcomp;
tsk_list_add_data(statehandler->compartments, ((void**) &newcomp));
tsk_list_push_back_data(statehandler->compartments, ((void**) &newcomp));
}
tsk_safeobj_unlock(statehandler);
@ -357,7 +357,7 @@ void tcomp_statehandler_addSipSdpDictionary(tcomp_statehandler_t *statehandler)
if(!statehandler->hasSipSdpDictionary)
{
tcomp_dictionary_t* sip_dict = tcomp_dicts_create_sip_dict();
tsk_list_add_data(statehandler->dictionaries, ((void**) &sip_dict));
tsk_list_push_back_data(statehandler->dictionaries, ((void**) &sip_dict));
statehandler->hasSipSdpDictionary = 1;
}
@ -379,7 +379,7 @@ void tcomp_statehandler_addPresenceDictionary(tcomp_statehandler_t *statehandler
if(!statehandler->hasPresenceDictionary)
{
tcomp_dictionary_t* pres_dict = tcomp_dicts_create_presence_dict();
tsk_list_add_data(statehandler->dictionaries, ((void**) &pres_dict));
tsk_list_push_back_data(statehandler->dictionaries, ((void**) &pres_dict));
statehandler->hasPresenceDictionary = 1;
}

View File

@ -2091,7 +2091,7 @@ int TCOMP_UDVM_EXEC_INST__END_MESSAGE(tcomp_udvm_t *udvm, uint16_t requested_fee
{
udvm->lpResult->remote_parameters->returnedStates = TSK_LIST_CREATE();
}
tsk_list_add_data(udvm->lpResult->remote_parameters->returnedStates, (void**)&partial_id);
tsk_list_push_back_data(udvm->lpResult->remote_parameters->returnedStates, (void**)&partial_id);
index += length;
}
}