diff --git a/include/Makefile.am b/include/Makefile.am
index f0c527c..f75bf54 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -12,6 +12,7 @@ nobase_include_HEADERS = trcomm.h \
tr/protocol/raw.h \
tr/protocol/message_raw.h \
tr/protocol_handler.h \
+ tr/server.h \
tr/interface/comm_end_point.h \
tr/interface/comm_manager.h \
tr/interface/protocol.h
diff --git a/include/tr/server.h b/include/tr/server.h
new file mode 100644
index 0000000..dd02153
--- /dev/null
+++ b/include/tr/server.h
@@ -0,0 +1,63 @@
+/**
+ * \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_SERVER_H__
+#define __TR_SERVER_H__
+
+#include
+
+#include "trbase.h"
+#include "trevent.h"
+
+#include "tr/comm_manager.h"
+#include "tr/connector.h"
+#include "tr/io_handler.h"
+#include "tr/protocol_handler.h"
+
+TR_CLASS(TR_Server) {
+ TR_CommManager comm_manager;
+ TR_EventDispatcher dispatcher;
+ TR_Connector connector;
+ TR_IoHandler io_handler;
+ TR_ProtocolHandler protocol_handler;
+};
+TR_INSTANCE_INIT(TR_Server);
+TR_CLASSVARS_DECL(TR_Server) {};
+
+#define TR_serverAddEndpoint(srv, ep) \
+ TR_commManagerAddEndpoint((srv)->comm_manager, (ep))
+
+#define TR_serverAddHandler(srv, handler) \
+ TR_eventDispatcherRegisterHandler((srv)->dispatcher, (handler))
+
+void TR_serverStart(TR_Server, int);
+
+#define TR_serverClassCleanup() \
+ TR_eventHandlerClassCleanup(TR_ProtocolHandler); \
+ TR_eventHandlerClassCleanup(TR_IoHandler); \
+ TR_eventHandlerClassCleanup(TR_Connector); \
+ TR_eventHandlerClassCleanup(TR_CommManagerPoll)
+
+#endif // __TR_SERVER_H__
+
+// vim: set ts=4 sw=4:
+
diff --git a/include/trcomm.h b/include/trcomm.h
index 4f78f77..bbade86 100644
--- a/include/trcomm.h
+++ b/include/trcomm.h
@@ -14,6 +14,7 @@
#include "tr/protocol/raw.h"
#include "tr/protocol/message_raw.h"
#include "tr/protocol_handler.h"
+#include "tr/server.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 4d8c089..f2cc430 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,6 +24,8 @@ TRCOMM = cep_append_read_data.c \
protocol_handler.c \
protocol_message_raw.c \
protocol_raw.c \
+ server.c \
+ server_start.c \
i_comm_end_point.c \
i_comm_manager.c \
i_protocol.c
diff --git a/src/i_comm_manager.c b/src/i_comm_manager.c
index 245a958..0793abf 100644
--- a/src/i_comm_manager.c
+++ b/src/i_comm_manager.c
@@ -112,7 +112,7 @@ TR_commManagerShutdownRead(void * _this, TR_Event event)
{
TR_CALL(_this, TR_CommManager, shutdownRead, event);
- if (TR_socketFinRd(((TR_CommEndPoint)event->subject)->transport)) {
+ if (TR_socketFinRdWr(((TR_CommEndPoint)event->subject)->transport)) {
// close
TR_eventHandlerIssueEvent(
(TR_EventHandler)_this,
@@ -120,7 +120,7 @@ TR_commManagerShutdownRead(void * _this, TR_Event event)
event->subject,
TR_CEP_EVENT_CLOSE,
NULL));
- } else if (TR_cepHasPendingData((TR_CommEndPoint)event->subject)) {
+ } else if (! TR_cepHasPendingData((TR_CommEndPoint)event->subject)) {
// handle pending data... close is issued from disableWrite
TR_eventHandlerIssueEvent(
(TR_EventHandler)_this,
diff --git a/src/io_handler.c b/src/io_handler.c
index d72c2c9..dc3d60d 100644
--- a/src/io_handler.c
+++ b/src/io_handler.c
@@ -87,21 +87,29 @@ ioHandlerWrite(void * _this, TR_Event event)
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject;
if (TR_cepWriteBuffered(endpoint)) {
- TR_Event new_event;
-
if (TR_cepHasPendingData(endpoint)) {
- new_event = TR_eventSubjectEmit(
- event->subject,
- TR_CEP_EVENT_PENDING_DATA,
- NULL);
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)_this,
+ TR_eventSubjectEmit(
+ event->subject,
+ TR_CEP_EVENT_PENDING_DATA,
+ NULL));
} else {
- new_event = TR_eventSubjectEmit(
- event->subject,
- TR_CEP_EVENT_END_DATA,
- NULL);
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)_this,
+ TR_eventSubjectEmit(
+ event->subject,
+ TR_CEP_EVENT_END_DATA,
+ NULL));
+ if (TRUE == endpoint->do_close) {
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)_this,
+ TR_eventSubjectEmit(
+ event->subject,
+ TR_CEP_EVENT_CLOSE,
+ NULL));
+ }
}
-
- TR_eventHandlerIssueEvent((TR_EventHandler)_this, new_event);
}
return TR_EVENT_DONE;
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..549ccac
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,83 @@
+/**
+ * \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 "trbase.h"
+#include "trio.h"
+#include "trevent.h"
+
+#include "tr/server.h"
+#include "tr/comm_manager.h"
+#include "tr/comm_manager_poll.h"
+#include "tr/connector.h"
+#include "tr/io_handler.h"
+#include "tr/protocol_handler.h"
+
+
+static
+int
+serverCtor(void * _this, va_list * params)
+{
+ TR_Server this = _this;
+
+ this->comm_manager = (TR_CommManager)TR_new(TR_CommManagerPoll);
+ this->dispatcher = TR_new(TR_EventDispatcher);
+ this->connector = TR_new(TR_Connector);
+ this->io_handler = TR_new(TR_IoHandler);
+ this->protocol_handler = TR_new(TR_ProtocolHandler);
+
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->comm_manager);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->connector);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->io_handler);
+ TR_eventDispatcherRegisterHandler(
+ this->dispatcher,
+ (TR_EventHandler)this->protocol_handler);
+
+ return 0;
+}
+
+static
+void
+serverDtor(void * _this)
+{
+ TR_Server this = _this;
+
+ TR_delete(this->protocol_handler);
+ TR_delete(this->io_handler);
+ TR_delete(this->connector);
+ TR_delete(this->dispatcher);
+ TR_delete(this->comm_manager);
+}
+
+TR_INIT_IFACE(TR_Class, serverCtor, serverDtor, NULL);
+TR_CREATE_CLASS(TR_Server, NULL, NULL, TR_IF(TR_Class));
+
+// vim: set ts=4 sw=4:
diff --git a/src/server_start.c b/src/server_start.c
new file mode 100644
index 0000000..8f67861
--- /dev/null
+++ b/src/server_start.c
@@ -0,0 +1,35 @@
+/**
+ * \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/server.h"
+
+void
+TR_serverStart(TR_Server this, int heartbeat)
+{
+ TR_eventDispatcherSetHeartbeat(this->dispatcher, 1000);
+ TR_eventDispatcherStart(this->dispatcher);
+}
+
+// vim: set ts=4 sw=4:
diff --git a/testers/build.sh b/testers/build.sh
index 6aa51e2..db1fdc3 100755
--- a/testers/build.sh
+++ b/testers/build.sh
@@ -1,4 +1,6 @@
#!/bin/bash
TRLIBS="-ltrbase -ltrhashing -ltrio -ltrdata -ltrevent -ltrcomm"
LIBS="-lcrypto -lssl -lrt -luuid"
-gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${TRLIBS} ${LIBS} -o testserver testserver.c
+gcc ${CFLAGS} -c -o test_handler.o test_handler.c
+gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${TRLIBS} ${LIBS} -o testserver testserver.c test_handler.o
+gcc ${CFLAGS} -I/usr/local/include -L/usr/local/lib ${TRLIBS} ${LIBS} -o testserver2 testserver2.c test_handler.o
diff --git a/testers/test_handler.c b/testers/test_handler.c
new file mode 100644
index 0000000..d8a9643
--- /dev/null
+++ b/testers/test_handler.c
@@ -0,0 +1,119 @@
+#include
+#include
+#include
+
+#include "trbase.h"
+#include "trcomm.h"
+#include "trevent.h"
+#include "test_handler.h"
+
+static
+TR_EventDone
+testHandlerHeartbeat(TR_EventHandler this, TR_Event event)
+{
+ printf("handled: %llu/s\n", ((TestHandler)this)->handled);
+ ((TestHandler)this)->handled = 0;
+
+ return TR_EVENT_DONE;
+}
+
+static
+TR_EventDone
+testHandlerNewMessage(TR_EventHandler this, TR_Event event)
+{
+ TR_ProtoMessageRaw msg = event->data;
+ TR_SizedData data = (TR_SizedData)msg->data;
+ char buf[data->size + 1];
+ int i;
+
+ ((TestHandler)this)->handled++;
+
+ memcpy(buf, data->data, data->size);
+ buf[data->size] = 0;
+ for (i = 0; buf[i]; i++) {
+ if (! isprint(buf[i])) buf[i] = '.';
+ }
+// printf("echo message: %s(%zd)\n", buf, data->size);
+
+ TR_eventHandlerIssueEvent(
+ (TR_EventHandler)this,
+ TR_eventSubjectEmit(
+ event->subject,
+ TR_CEP_EVENT_SEND_MSG,
+ event->data));
+
+ return TR_EVENT_DONE;
+}
+
+static
+TR_EventDone
+testHandlerClose(TR_EventHandler this, TR_Event event)
+{
+ puts("close");
+
+ return TR_EVENT_PENDING;
+}
+
+static
+TR_EventDone
+testHandlerUpgrade(TR_EventHandler this, TR_Event event)
+{
+ printf("upgrade: %"PRIdPTR"\n", event->id);
+
+ return TR_EVENT_PENDING;
+}
+
+static
+int
+testHandlerCtor(void * _this, va_list * params)
+{
+ TR_PARENTCALL(TestHandler, _this, TR_Class, ctor, params);
+ ((TestHandler)_this)->handled = 0;
+
+ return 0;
+}
+
+static
+void
+testHandlerDtor(void * _this, va_list * params)
+{
+ TR_PARENTCALL(TestHandler, _this, TR_Class, dtor);
+}
+
+static
+void
+testHandlerCvInit(TR_class_ptr class)
+{
+ TR_EVENT_HANDLER_SET_METHOD(
+ class,
+ TR_EventDispatcher,
+ TR_DISPATCHER_EVENT_HEARTBEAT,
+ testHandlerHeartbeat);
+ TR_EVENT_HANDLER_SET_METHOD(
+ class,
+ TR_CommEndPoint,
+ TR_CEP_EVENT_NEW_MSG,
+ testHandlerNewMessage);
+ TR_EVENT_HANDLER_SET_METHOD(
+ class,
+ TR_CommEndPoint,
+ TR_CEP_EVENT_CLOSE,
+ testHandlerClose);
+ TR_EVENT_HANDLER_SET_METHOD(
+ class,
+ TR_CommEndPoint,
+ TR_CEP_EVENT_UPGRADE,
+ testHandlerUpgrade);
+}
+
+TR_INSTANCE(TR_Hash, testHandlerEventMethods);
+TR_INIT_IFACE(TR_Class, testHandlerCtor, testHandlerDtor, NULL);
+TR_CREATE_CLASS(
+ TestHandler,
+ TR_EventHandler,
+ testHandlerCvInit,
+ TR_IF(TR_Class)) = {
+ { &(_testHandlerEventMethods.data) }
+};
+
+// vim: set ts=4 sw=4:
diff --git a/testers/test_handler.h b/testers/test_handler.h
new file mode 100644
index 0000000..61111b6
--- /dev/null
+++ b/testers/test_handler.h
@@ -0,0 +1,18 @@
+#include
+#include
+#include
+
+#include "trbase.h"
+#include "trcomm.h"
+#include "trevent.h"
+
+TR_CLASS(TestHandler) {
+ TR_EXTENDS(TR_EventHandler);
+ unsigned long long handled;
+};
+TR_INSTANCE_INIT(TestHandler);
+TR_CLASSVARS_DECL(TestHandler) {
+ TR_CV_EXTENDS(TR_EventHandler);
+};
+
+// vim: set ts=4 sw=4:
diff --git a/testers/testserver.c b/testers/testserver.c
index 1c4bfc6..daca046 100644
--- a/testers/testserver.c
+++ b/testers/testserver.c
@@ -6,123 +6,7 @@
#include "trcomm.h"
#include "trevent.h"
-TR_CLASS(TestHandler) {
- TR_EXTENDS(TR_EventHandler);
- unsigned long long handled;
-};
-TR_INSTANCE_INIT(TestHandler);
-TR_CLASSVARS_DECL(TestHandler) {
- TR_CV_EXTENDS(TR_EventHandler);
-};
-
-static
-TR_EventDone
-testHandlerHeartbeat(TR_EventHandler this, TR_Event event)
-{
- printf("handled: %llu/s\n", ((TestHandler)this)->handled);
- ((TestHandler)this)->handled = 0;
-
- return TR_EVENT_DONE;
-}
-
-static
-TR_EventDone
-testHandlerNewMessage(TR_EventHandler this, TR_Event event)
-{
- TR_ProtoMessageRaw msg = event->data;
- TR_SizedData data = (TR_SizedData)msg->data;
- char buf[data->size + 1];
- int i;
-
- ((TestHandler)this)->handled++;
-
- memcpy(buf, data->data, data->size);
- buf[data->size] = 0;
- for (i = 0; buf[i]; i++) {
- if (! isprint(buf[i])) buf[i] = '.';
- }
- printf("echo message: %s(%zd)\n", buf, data->size);
-
- TR_eventHandlerIssueEvent(
- (TR_EventHandler)this,
- TR_eventSubjectEmit(
- event->subject,
- TR_CEP_EVENT_SEND_MSG,
- event->data));
-
- return TR_EVENT_DONE;
-}
-
-static
-TR_EventDone
-testHandlerClose(TR_EventHandler this, TR_Event event)
-{
- puts("close");
-
- return TR_EVENT_PENDING;
-}
-
-static
-TR_EventDone
-testHandlerUpgrade(TR_EventHandler this, TR_Event event)
-{
- printf("upgrade: %"PRIdPTR"\n", event->id);
-
- return TR_EVENT_PENDING;
-}
-
-static
-int
-testHandlerCtor(void * _this, va_list * params)
-{
- TR_PARENTCALL(TestHandler, _this, TR_Class, ctor, params);
- ((TestHandler)_this)->handled = 0;
-
- return 0;
-}
-
-static
-void
-testHandlerDtor(void * _this, va_list * params)
-{
- TR_PARENTCALL(TestHandler, _this, TR_Class, dtor);
-}
-
-static
-void
-testHandlerCvInit(TR_class_ptr class)
-{
- TR_EVENT_HANDLER_SET_METHOD(
- class,
- TR_EventDispatcher,
- TR_DISPATCHER_EVENT_HEARTBEAT,
- testHandlerHeartbeat);
- TR_EVENT_HANDLER_SET_METHOD(
- class,
- TR_CommEndPoint,
- TR_CEP_EVENT_NEW_MSG,
- testHandlerNewMessage);
- TR_EVENT_HANDLER_SET_METHOD(
- class,
- TR_CommEndPoint,
- TR_CEP_EVENT_CLOSE,
- testHandlerClose);
- TR_EVENT_HANDLER_SET_METHOD(
- class,
- TR_CommEndPoint,
- TR_CEP_EVENT_UPGRADE,
- testHandlerUpgrade);
-}
-
-TR_INSTANCE(TR_Hash, testHandlerEventMethods);
-TR_INIT_IFACE(TR_Class, testHandlerCtor, testHandlerDtor, NULL);
-TR_CREATE_CLASS(
- TestHandler,
- TR_EventHandler,
- testHandlerCvInit,
- TR_IF(TR_Class)) = {
- { &(_testHandlerEventMethods.data) }
-};
+#include "test_handler.h"
TR_INSTANCE(TR_LoggerSyslog, mylogger, {TR_LOGGER_DEBUG});
@@ -135,13 +19,10 @@ main (int argc, char * argv[])
TR_IoHandler io_handler = TR_new(TR_IoHandler);
TR_ProtocolHandler protocol_handler = TR_new(TR_ProtocolHandler);
TestHandler test_handler = TR_new(TestHandler);
-#if 0
- TR_ConnEntryPoint ep;
- TR_TcpSocket ep_sock;
-#else
- TR_DatagramService ep;
- TR_UdpSocket ep_sock;
-#endif
+ TR_ConnEntryPoint tcp_ep;
+ TR_TcpSocket tcp_ep_sock;
+ TR_DatagramService udp_ep;
+ TR_UdpSocket udp_ep_sock;
TR_Protocol protocol;
TR_logger = TR_INSTANCE_CAST(TR_Logger, mylogger);
@@ -157,17 +38,15 @@ main (int argc, char * argv[])
(TR_EventHandler)test_handler);
protocol = TR_new(TR_ProtocolRaw);
-#if 0
- ep_sock = TR_new(TR_TcpSocket, TR_logger, "0.0.0.0", 5678, 0);
- ep = TR_new(TR_ConnEntryPoint, ep_sock, protocol);
-#else
- ep_sock = TR_new(TR_UdpSocket, TR_logger, "0.0.0.0", 5678, 0);
- TR_socketBind((TR_Socket)ep_sock);
- TR_socketNonblock((TR_Socket)ep_sock);
- ep = TR_new(TR_DatagramService, ep_sock, protocol);
-#endif
-
- TR_commManagerAddEndpoint(cmgr, (TR_CommEndPoint)ep);
+ tcp_ep_sock = TR_new(TR_TcpSocket, TR_logger, "0.0.0.0", 5678, 0);
+ tcp_ep = TR_new(TR_ConnEntryPoint, tcp_ep_sock, protocol);
+ udp_ep_sock = TR_new(TR_UdpSocket, TR_logger, "0.0.0.0", 5678, 0);
+ TR_socketBind((TR_Socket)udp_ep_sock);
+ TR_socketNonblock((TR_Socket)udp_ep_sock);
+ udp_ep = TR_new(TR_DatagramService, udp_ep_sock, protocol);
+
+ TR_commManagerAddEndpoint(cmgr, (TR_CommEndPoint)tcp_ep);
+ TR_commManagerAddEndpoint(cmgr, (TR_CommEndPoint)udp_ep);
TR_eventDispatcherSetHeartbeat(dispatcher, 1000);
TR_eventDispatcherStart(dispatcher);
diff --git a/testers/testserver2.c b/testers/testserver2.c
new file mode 100644
index 0000000..9f641d6
--- /dev/null
+++ b/testers/testserver2.c
@@ -0,0 +1,54 @@
+#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_DEBUG});
+
+int
+main (int argc, char * argv[])
+{
+ TR_Server server = TR_new(TR_Server);
+ TR_Protocol protocol = TR_new(TR_ProtocolRaw);
+ TestHandler test_handler = TR_new(TestHandler);
+ TR_Socket socket;
+
+ TR_logger = TR_INSTANCE_CAST(TR_Logger, mylogger);
+
+ TR_serverAddHandler(server, (TR_EventHandler)test_handler);
+ socket = (TR_Socket)TR_new(TR_TcpSocket, TR_logger, "0.0.0.0", 5678, 0);
+ TR_serverAddEndpoint(
+ server,
+ TR_new(TR_ConnEntryPoint, socket, protocol));
+
+ socket = TR_new(TR_UdpSocket, TR_logger, "0.0.0.0", 5678, 0);
+ TR_socketBind((TR_Socket)socket);
+ TR_socketNonblock((TR_Socket)socket);
+ TR_serverAddEndpoint(
+ server,
+ TR_new(TR_DatagramService, socket, protocol));
+
+ TR_serverStart(server, 1000);
+
+ puts("cleanup...");
+
+ TR_delete(server);
+ TR_delete(test_handler);
+ TR_delete(protocol);
+ //TR_delete(ep);
+
+ TR_eventHandlerClassCleanup(TestHandler);
+ TR_serverClassCleanup();
+
+ TR_cleanup();
+
+ return 0;
+}
+
+// vim: set ts=4 sw=4: