/** * \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 int datagramServiceCompose(void * _this, TR_ProtoMessage message) { TR_RemoteData data = TR_protoCompose(((TR_CommEndPoint)_this)->protocol, message); if (! data) { return FALSE; } TR_queuePut(((TR_CommEndPoint)_this)->write_buffer, data); return TRUE; } 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: