diff --git a/include/Makefile.am b/include/Makefile.am index d3fb157..f0c527c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -5,6 +5,7 @@ nobase_include_HEADERS = trcomm.h \ tr/connect_entry_point.h \ tr/connection.h \ tr/connector.h \ + tr/datagram_service.h \ tr/io_handler.h \ tr/proto_message.h \ tr/protocol.h \ diff --git a/include/tr/connection.h b/include/tr/connection.h index 66f7385..858ea45 100644 --- a/include/tr/connection.h +++ b/include/tr/connection.h @@ -45,9 +45,6 @@ TR_CLASSVARS_DECL(TR_Connection) { #define TR_CON_EVENT_NEW_CON (TR_CEP_EVENT_MAX + 1) #define TR_CON_EVENT_MAX ((size_t)TR_CON_EVENT_NEW_CON) -TR_ProtoMessage TR_conNextMessage(TR_Connection); -int TR_conCompose(TR_Connection, TR_ProtoMessage); - #endif // __TR_CONNECTION_H__ // vim: set ts=4 sw=4: diff --git a/include/tr/datagram_service.h b/include/tr/datagram_service.h new file mode 100644 index 0000000..f6565f3 --- /dev/null +++ b/include/tr/datagram_service.h @@ -0,0 +1,49 @@ +/** + * \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_DATAGRAM_SERVICE_H__ +#define __TR_DATAGRAM_SERVICE_H__ + +#include + +#include "trbase.h" +#include "trevent.h" +#include "trdata.h" + +#include "tr/comm_end_point.h" +#include "tr/proto_message.h" + +TR_CLASS(TR_DatagramService) { + TR_EXTENDS(TR_CommEndPoint); +}; +TR_INSTANCE_INIT(TR_DatagramService); +TR_CLASSVARS_DECL(TR_DatagramService) { + TR_CV_EXTENDS(TR_CommEndPoint); +}; + +TR_ProtoMessage TR_dsNextMessage(TR_DatagramService); +int TR_dsCompose(TR_DatagramService, TR_ProtoMessage); + +#endif // __TR_DATAGRAM_SERVICE_H__ + +// vim: set ts=4 sw=4: + diff --git a/include/trcomm.h b/include/trcomm.h index ece0783..4f78f77 100644 --- a/include/trcomm.h +++ b/include/trcomm.h @@ -7,6 +7,7 @@ #include "tr/connect_entry_point.h" #include "tr/connection.h" #include "tr/connector.h" +#include "tr/datagram_service.h" #include "tr/io_handler.h" #include "tr/proto_message.h" #include "tr/protocol.h" diff --git a/src/Makefile.am b/src/Makefile.am index a2bb75a..4d8c089 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,6 +17,7 @@ TRCOMM = cep_append_read_data.c \ conn_entry_point.c \ connection.c \ connector.c \ + datagram_service.c \ io_handler.c \ proto_message.c \ protocol.c \ diff --git a/src/datagram_service.c b/src/datagram_service.c new file mode 100644 index 0000000..c7379a8 --- /dev/null +++ b/src/datagram_service.c @@ -0,0 +1,128 @@ +/** + * \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 "trdata.h" + +#include "tr/datagram_service.h" +#include "tr/interface/protocol.h" +#include "tr/interface/comm_end_point.h" + +static +int +datagramServiceCtor(void * _this, va_list * params) +{ + TR_PARENTCALL(TR_DatagramService, _this, TR_Class, ctor, params); + + return 0; +} + +static +void +datagramServiceDtor(void * _this) +{ + TR_PARENTCALL(TR_DatagramService, _this, TR_Class, dtor); +} + +static +TR_ProtoMessage +datagramServiceNextMessage(void * _this) +{ + TR_CommEndPoint comm = _this; + TR_RemoteData data = TR_queueGet(comm->read_buffer); + TR_ProtoMessage ret_message = NULL; + size_t end; + + if (NULL == data) return ret_message; + + ret_message = TR_protoCreateMessage(comm->protocol, data->remote); + end = TR_protoParse(comm->protocol, ret_message, data); + + if (end != ((TR_SizedData)data)->size) { + /** + * TODO + * This means that the parser has not consumed all of the data. + * We do not know the reason, but with HTTP this should only occur + * when the message is complete... anyway, to prevent us from + * looping forever because a protocol implementation is buggy + * we should close the connection after end was 0 the second time. + * This can be done by firing a close event. + */ + switch(end) { + default: + { + TR_RemoteData new_data = TR_new( + TR_RemoteData, + ((TR_SizedData)data)->data + end, + ((TR_SizedData)data)->size - end, + data->remote); + TR_delete(data); + data = new_data; + } + // intended drop through + + case 0: + TR_queuePutFirst(comm->read_buffer, data); + } + } + + if (! ret_message->ready) { + TR_delete(ret_message); + } + + return ret_message; +} + +static +void +datagramServiceCompose(void * _this, TR_ProtoMessage message) +{ + TR_queuePut( + ((TR_CommEndPoint)_this)->write_buffer, + TR_protoCompose(((TR_CommEndPoint)_this)->protocol, message)); +} + +intptr_t datagramService_events[TR_CEP_EVENT_MAX + 1]; +TR_INIT_IFACE(TR_Class, datagramServiceCtor, datagramServiceDtor, NULL); +TR_INIT_IFACE( + TR_CommEndPoint, + datagramServiceNextMessage, + datagramServiceCompose); +TR_CREATE_CLASS( + TR_DatagramService, + TR_CommEndPoint, + NULL, + TR_IF(TR_Class), + TR_IF(TR_CommEndPoint)) = { + {{ + TR_CEP_EVENT_MAX + 1, + datagramService_events + }} +}; + +// vim: set ts=4 sw=4: diff --git a/testers/build.sh b/testers/build.sh old mode 100644 new mode 100755 diff --git a/testers/testserver.c b/testers/testserver.c index b05b434..881f16f 100644 --- a/testers/testserver.c +++ b/testers/testserver.c @@ -39,7 +39,7 @@ testHandlerNewMessage(TR_EventHandler this, TR_Event event) for (i = 0; buf[i]; i++) { if (! isprint(buf[i])) buf[i] = '.'; } -// printf("echo message: %s(%zd)\n", buf, data->size); + printf("echo message: %s(%zd)\n", buf, data->size); TR_eventHandlerIssueEvent( (TR_EventHandler)this, @@ -130,8 +130,13 @@ 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_Protocol protocol; TR_logger = TR_INSTANCE_CAST(TR_Logger, mylogger); @@ -147,8 +152,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);