diff --git a/.gitignore b/.gitignore
index 9c409e8..8c695b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,4 @@ test-driver
tags
/trcomm.h*
/testers/testserver*
+/testers/testclient*
diff --git a/include/Makefile.am b/include/Makefile.am
index 937e6a4..38ac4a6 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -15,6 +15,7 @@ nobase_include_HEADERS = trcomm.h \
tr/protocol/message_raw.h \
tr/protocol_handler.h \
tr/server.h \
+ tr/simple_client.h \
tr/interface/comm_end_point.h \
tr/interface/comm_manager.h \
tr/interface/protocol.h
diff --git a/include/tr/interface/comm_manager.h b/include/tr/interface/comm_manager.h
index 74f0a43..d4c073e 100644
--- a/include/tr/interface/comm_manager.h
+++ b/include/tr/interface/comm_manager.h
@@ -31,7 +31,7 @@
#include "tr/comm_end_point.h"
typedef TR_EventDone (* fptr_TR_commManagerAddEndpoint)(void *, TR_CommEndPoint);
-typedef TR_EventDone (* fptr_TR_commManagerSelect)(void *, TR_Event, int);
+typedef TR_EventDone (* fptr_TR_commManagerSelect)(void *, TR_Event, unsigned long);
typedef TR_EventDone (* fptr_TR_commManagerPollWrite)(void *, TR_Event);
typedef TR_EventDone (* fptr_TR_commManagerPollRead)(void *, TR_Event);
typedef TR_EventDone (* fptr_TR_commManagerDisableWrite)(void *, TR_Event);
diff --git a/include/tr/server.h b/include/tr/server.h
index 9a56213..ce5eb42 100644
--- a/include/tr/server.h
+++ b/include/tr/server.h
@@ -53,7 +53,7 @@ TR_CLASSVARS_DECL(TR_Server) {};
void TR_serverBindTcp(TR_Server, const char *, int, TR_Protocol);
void TR_serverBindUdp(TR_Server, const char *, int, TR_Protocol);
-void TR_serverStart(TR_Server, int);
+void TR_serverStart(TR_Server, unsigned long);
#define TR_serverClassCleanup() \
TR_eventHandlerClassCleanup(TR_ProtocolHandler); \
diff --git a/include/tr/simple_client.h b/include/tr/simple_client.h
new file mode 100644
index 0000000..2d2c1bd
--- /dev/null
+++ b/include/tr/simple_client.h
@@ -0,0 +1,70 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2014 Georg Hopp
+ *
+ * This program 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.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __TR_SIMPLE_CLIENT_H__
+#define __TR_SIMPLE_CLIENT_H__
+
+#include
+#include
+
+#include "trbase.h"
+#include "trevent.h"
+
+#include "tr/comm_manager.h"
+#include "tr/comm_end_point.h"
+#include "tr/io_handler.h"
+#include "tr/protocol_handler.h"
+#include "tr/protocol.h"
+#include "tr/proto_message.h"
+#include "tr/interface/comm_manager.h"
+
+TR_CLASS(TR_SimpleClient) {
+ TR_EXTENDS(TR_EventHandler);
+
+ TR_CommEndPoint endpoint;
+ TR_CommManager comm_manager;
+ TR_ProtoMessage request;
+ TR_ProtoMessage response;
+ TR_IoHandler io_handler;
+ TR_ProtocolHandler protocol_handler;
+ TR_EventDispatcher dispatcher;
+ int send_issued;
+ TR_Timer timer;
+};
+TR_INSTANCE_INIT(TR_SimpleClient);
+TR_CLASSVARS_DECL(TR_SimpleClient) {
+ TR_CV_EXTENDS(TR_EventHandler);
+};
+
+TR_ProtoMessage TR_simpleClientIssue(
+ TR_SimpleClient, TR_ProtoMessage, unsigned long);
+
+#define TR_simpleClientClassCleanup() \
+ TR_eventHandlerClassCleanup(TR_ProtocolHandler); \
+ TR_eventHandlerClassCleanup(TR_IoHandler); \
+ TR_eventHandlerClassCleanup(TR_CommManagerEpoll); \
+ TR_eventHandlerClassCleanup(TR_SimpleClient)
+
+#endif // __TR_SIMPLE_CLIENT_H__
+
+// vim: set ts=4 sw=4:
+
diff --git a/include/trcomm.h b/include/trcomm.h
index e6d26f2..b2691f9 100644
--- a/include/trcomm.h
+++ b/include/trcomm.h
@@ -17,6 +17,7 @@
#include "tr/protocol/message_raw.h"
#include "tr/protocol_handler.h"
#include "tr/server.h"
+#include "tr/simple_client.h"
#include "tr/interface/comm_end_point.h"
#include "tr/interface/comm_manager.h"
#include "tr/interface/protocol.h"
diff --git a/src/Makefile.am b/src/Makefile.am
index bb54599..235169a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,8 @@ TRCOMM = cet_accept.c \
server_bind_tcp.c \
server_bind_udp.c \
server_start.c \
+ simple_client.c \
+ simple_client_issue.c \
i_comm_end_point.c \
i_comm_manager.c \
i_protocol.c
diff --git a/src/comm_manager.c b/src/comm_manager.c
index 01a0a7e..3f893a4 100644
--- a/src/comm_manager.c
+++ b/src/comm_manager.c
@@ -40,9 +40,14 @@ commManagerCtor(void * _this, va_list * params)
TR_PARENTCALL(TR_CommManager, _this, TR_Class, ctor, params);
- this->accept = TR_new(TR_Hash);
- this->write = TR_new(TR_Hash);
- this->read = TR_new(TR_Hash);
+ this->accept = TR_new(TR_Hash);
+ this->write = TR_new(TR_Hash);
+ this->read = TR_new(TR_Hash);
+
+ this->accept->cleanup_no_free = TRUE;
+ this->write->cleanup_no_free = TRUE;
+ this->read->cleanup_no_free = TRUE;
+
this->n_endpoints = sysconf(_SC_OPEN_MAX);
this->endpoints = TR_calloc(sizeof(TR_CommEndPoint), this->n_endpoints);
@@ -56,7 +61,7 @@ commManagerDtor(void * _this)
TR_CommManager this = _this;
nfds_t i;
- for (i = 0; i < this->n_endpoints; i++) {
+ for (i=0; in_endpoints; i++) {
TR_delete(this->endpoints[i]);
}
TR_MEM_FREE(this->endpoints);
@@ -85,7 +90,7 @@ TR_commManagerAddEndpointEvt(TR_CommManager this, TR_Event event)
return TR_EVENT_DONE;
}
-TR_EventDone TR_commManagerSelect(void *, TR_Event, int);
+TR_EventDone TR_commManagerSelect(void *, TR_Event);
TR_EventDone TR_commManagerPollWrite(void *, TR_Event);
TR_EventDone TR_commManagerPollRead(void *, TR_Event);
TR_EventDone TR_commManagerDisableRead(void *, TR_Event);
diff --git a/src/comm_manager_epoll.c b/src/comm_manager_epoll.c
index 164034b..72cdfe8 100644
--- a/src/comm_manager_epoll.c
+++ b/src/comm_manager_epoll.c
@@ -83,7 +83,7 @@ TR_commManagerEpollAddEndpoint(void * _this, TR_CommEndPoint endpoint)
static
void
-TR_commManagerEpollSelect(void * _this, TR_Event event, int timeout)
+TR_commManagerEpollSelect(void * _this, TR_Event event, unsigned long timeout)
{
TR_CommManagerEpoll this = _this;
TR_CommManager cmgr = _this;
diff --git a/src/comm_manager_poll.c b/src/comm_manager_poll.c
index 4bd3e5f..e5bcb16 100644
--- a/src/comm_manager_poll.c
+++ b/src/comm_manager_poll.c
@@ -61,6 +61,7 @@ commManagerPollDtor(void * _this)
TR_CommManagerPoll this = _this;
TR_MEM_FREE(this->fds);
+ TR_PARENTCALL(TR_CommManagerPoll, _this, TR_Class, dtor);
}
static
@@ -75,7 +76,7 @@ TR_commManagerPollAddEndpoint(void * _this, TR_CommEndPoint endpoint)
static
void
-TR_commManagerPollSelect(void * _this, TR_Event event, int timeout)
+TR_commManagerPollSelect(void * _this, TR_Event event, unsigned long timeout)
{
TR_CommManagerPoll this = _this;
TR_CommManager cmgr = _this;
diff --git a/src/i_comm_manager.c b/src/i_comm_manager.c
index 00fc9f4..d6f5344 100644
--- a/src/i_comm_manager.c
+++ b/src/i_comm_manager.c
@@ -86,19 +86,19 @@ commManagerIssueReadEvents(const void * endpoint, const void * comm_manager)
TR_EventDone
TR_commManagerSelect(void * _this, TR_Event event)
{
- TR_CommManager this = _this;
- int timeout; // milliseconds
- int * timeoutptr = event->data;
- TR_EventDispatcher dispatcher = (TR_EventDispatcher)event->subject;
+ TR_CommManager this = _this;
+ TR_Timer timer = (TR_Timer)event->data;
+ TR_EventDispatcher dispatcher = (TR_EventDispatcher)event->subject;
+ unsigned long timeout; // milliseconds
if (! (TR_hashEmpty(this->read)
&& TR_hashEmpty(this->write)
&& TR_hashEmpty(this->accept))) {
timeout = 0;
- } else if (NULL == timeoutptr) {
+ } else if (NULL == timer) {
timeout = TR_eventDispatcherGetDataWaitTime(dispatcher);
} else {
- timeout = *timeoutptr;
+ timeout = TR_timerGet(timer, NULL);
}
TR_CALL(_this, TR_CommManager, select, event, timeout);
diff --git a/src/server.c b/src/server.c
index adb4ef8..7fda748 100644
--- a/src/server.c
+++ b/src/server.c
@@ -48,7 +48,7 @@ serverCtor(void * _this, va_list * params)
#else
this->comm_manager = (TR_CommManager)TR_new(TR_CommManagerPoll);
#endif
- this->dispatcher = TR_new(TR_EventDispatcher, TR_EVD_SERVER, NULL, 100);
+ this->dispatcher = TR_new(TR_EventDispatcher, TR_EVD_SERVER, NULL);
this->connector = TR_new(TR_Connector);
this->io_handler = TR_new(TR_IoHandler);
this->protocol_handler = TR_new(TR_ProtocolHandler);
diff --git a/src/server_start.c b/src/server_start.c
index 8f67861..4a9ed9b 100644
--- a/src/server_start.c
+++ b/src/server_start.c
@@ -26,9 +26,9 @@
#include "tr/server.h"
void
-TR_serverStart(TR_Server this, int heartbeat)
+TR_serverStart(TR_Server this, unsigned long heartbeat)
{
- TR_eventDispatcherSetHeartbeat(this->dispatcher, 1000);
+ TR_eventDispatcherSetHeartbeat(this->dispatcher, heartbeat);
TR_eventDispatcherStart(this->dispatcher);
}
diff --git a/src/simple_client.c b/src/simple_client.c
new file mode 100644
index 0000000..dd70237
--- /dev/null
+++ b/src/simple_client.c
@@ -0,0 +1,160 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2014 Georg Hopp
+ *
+ * This program 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.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include
+#include
+
+#include "trbase.h"
+#include "trio.h"
+#include "trevent.h"
+
+#include "tr/simple_client.h"
+#include "tr/comm_end_point.h"
+#include "tr/comm_manager.h"
+#include "tr/comm_manager_poll.h"
+#include "tr/comm_manager_epoll.h"
+#include "tr/connector.h"
+#include "tr/io_handler.h"
+#include "tr/protocol_handler.h"
+
+
+static
+int
+simpleClientCtor(void * _this, va_list * params)
+{
+ TR_SimpleClient this = _this;
+
+ this->endpoint = va_arg(*params, TR_CommEndPoint);
+
+#if 1
+ this->comm_manager = (TR_CommManager)TR_new(TR_CommManagerEpoll);
+#else
+ this->comm_manager = (TR_CommManager)TR_new(TR_CommManagerPoll);
+#endif
+ this->dispatcher = TR_new(TR_EventDispatcher, TR_EVD_CLIENT, NULL);
+ this->io_handler = TR_new(TR_IoHandler);
+ this->protocol_handler = TR_new(TR_ProtocolHandler);
+ this->timer = TR_new(TR_Timer, TR_TBASE_MIL, 1000);
+
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->comm_manager);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->io_handler);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->protocol_handler);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this);
+
+ TR_commManagerAddEndpoint(this->comm_manager, this->endpoint);
+
+ return 0;
+}
+
+static
+void
+simpleClientDtor(void * _this)
+{
+ TR_SimpleClient this = _this;
+
+ TR_delete(this->protocol_handler);
+ TR_delete(this->io_handler);
+ TR_delete(this->comm_manager);
+ TR_delete(this->dispatcher);
+ TR_delete(this->timer);
+}
+
+static
+TR_EventDone
+simpleClientUserAction(void * _this, TR_Event event)
+{
+ TR_SimpleClient this = _this;
+
+ if (this->send_issued) {
+ unsigned long missed;
+
+ TR_timerGet(this->timer, &missed);
+
+ if (this->response || missed) {
+ TR_eventDispatcherStop((TR_EventDispatcher)event->subject);
+ } else {
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)_this,
+ TR_eventSubjectEmit(
+ event->subject,
+ TR_DISPATCHER_EVENT_DATA_WAIT,
+ this->timer));
+ }
+ } else {
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)_this,
+ TR_eventSubjectEmit(
+ (TR_EventSubject)this->endpoint,
+ TR_CEP_EVENT_MSG_READY,
+ this->request));
+ this->send_issued = TRUE;
+ }
+
+ return TR_EVENT_DONE;
+}
+
+static
+TR_EventDone
+simpleClientHandleData(void * _this, TR_Event event)
+{
+ ((TR_SimpleClient)_this)->response = event->data;
+
+ return TR_EVENT_DONE;
+}
+
+static
+void
+simpleClientCvInit(TR_class_ptr cls)
+{
+ TR_EVENT_HANDLER_SET_METHOD(
+ cls,
+ TR_EventDispatcher,
+ TR_DISPATCHER_EVENT_USER_WAIT,
+ simpleClientUserAction);
+ TR_EVENT_HANDLER_SET_METHOD(
+ cls,
+ TR_CommEndPoint,
+ TR_CEP_EVENT_NEW_MSG,
+ simpleClientHandleData);
+}
+
+TR_INSTANCE(TR_Hash, simpleClientEventMethods);
+TR_INIT_IFACE(TR_Class, simpleClientCtor, simpleClientDtor, NULL);
+TR_CREATE_CLASS(
+ TR_SimpleClient,
+ TR_EventHandler,
+ simpleClientCvInit,
+ TR_IF(TR_Class)) = {
+ { &(_simpleClientEventMethods.data) }
+};
+
+// vim: set ts=4 sw=4:
diff --git a/src/simple_client_issue.c b/src/simple_client_issue.c
new file mode 100644
index 0000000..bb7affb
--- /dev/null
+++ b/src/simple_client_issue.c
@@ -0,0 +1,50 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2014 Georg Hopp
+ *
+ * This program 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.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "trbase.h"
+#include "trevent.h"
+
+#include "tr/simple_client.h"
+#include "tr/proto_message.h"
+
+TR_ProtoMessage
+TR_simpleClientIssue(
+ TR_SimpleClient this,
+ TR_ProtoMessage request,
+ unsigned long timeout)
+{
+ TR_ProtoMessage retval;
+
+ TR_timerSetMil(this->timer, timeout);
+ this->request = request;
+ this->response = NULL;
+ this->send_issued = FALSE;
+
+ TR_eventDispatcherStart(((TR_EventHandler)this)->dispatcher[0]);
+
+ retval = this->response;
+ this->request = this->response = NULL;
+
+ return retval;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/testers/build.sh b/testers/build.sh
index fda4ed3..8fafec4 100755
--- a/testers/build.sh
+++ b/testers/build.sh
@@ -5,3 +5,4 @@ LIBS="-lcrypto -lssl -lrt -luuid"
gcc ${CFLAGS} -c -o test_handler.o test_handler.c
gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${LIBS} -o testserver testserver.c test_handler.o ${TRLIBS}
gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${LIBS} -o testserver2 testserver2.c test_handler.o ${TRLIBS}
+gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${LIBS} -o testclient testclient.c ${TRLIBS}
diff --git a/testers/testclient.c b/testers/testclient.c
new file mode 100644
index 0000000..e24db17
--- /dev/null
+++ b/testers/testclient.c
@@ -0,0 +1,59 @@
+#include
+#include
+#include
+
+#include "trbase.h"
+#include "trcomm.h"
+#include "trio.h"
+#include "trevent.h"
+
+#include "test_handler.h"
+
+TR_INSTANCE(TR_LoggerSyslog, mylogger, {TR_LOGGER_INFO});
+TR_INSTANCE(TR_LoggerStderr, mylogger2, {TR_LOGGER_INFO});
+
+int
+main (int argc, char * argv[])
+{
+ TR_TcpSocket socket;
+ TR_Connection connection;
+ TR_SimpleClient client;
+ TR_Protocol protocol;
+ TR_ProtoMessageRaw message;
+ TR_RemoteData data;
+
+ TR_logger = TR_INSTANCE_CAST(TR_Logger, mylogger2);
+ socket = TR_new(TR_TcpSocket, TR_logger, "192.168.2.13", 5678, 0);
+ protocol = TR_new(TR_ProtocolRaw);
+ connection = TR_new(TR_Connection, socket, protocol);
+
+ TR_socketConnect((TR_Socket)socket);
+ TR_socketNonblock((TR_Socket)socket);
+
+ client = TR_new(TR_SimpleClient, connection);
+
+ message = (TR_ProtoMessageRaw)TR_protoCreateRequest(protocol, (TR_Socket)socket);
+ data = TR_new(TR_RemoteData, "test", sizeof("test"), (TR_Socket)socket);
+ message->data = data;
+ message = (TR_ProtoMessageRaw)TR_simpleClientIssue(
+ client,
+ (TR_ProtoMessage)message,
+ 10000000);
+
+ printf("%s\n", ((TR_SizedData)message->data)->data);
+ TR_delete(message->data);
+ TR_delete(message);
+
+ puts("cleanup...");
+
+ TR_delete(client);
+ TR_delete(protocol);
+
+ TR_simpleClientClassCleanup();
+
+ TR_cleanup();
+
+ return 0;
+}
+
+// vim: set ts=4 sw=4: