/** * \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 #include #include "trbase.h" #include "trio.h" #include "tr/protocol/raw.h" #include "tr/protocol/message_raw.h" #include "tr/interface/protocol.h" static int protocolRawCtor(void * _this, va_list * params) { return 0; } static void protocolRawDtor(void * _this) {} static TR_ProtoMessage protocolRawCreateMessage(void * _this, va_list * args) { return (TR_ProtoMessage)TR_new(TR_ProtoMessageRaw); } static TR_RemoteData protocolRawParse(void * _this, TR_ProtoMessage _message, TR_RemoteData _data) { TR_ProtoMessageRaw message = (TR_ProtoMessageRaw)_message; size_t size = ((TR_SizedData)_data)->size; char * data = ((TR_SizedData)_data)->data; TR_RemoteData retval = NULL; if (! message->data) { if (message->size == 0) { if (size == 1) { message->size = *(char *)data << 8; TR_delete(_data); return NULL; } else { message->size = *(uint16_t *)data; size -= 2; data += 2; } } else { message->size &= *(char *)data; size--; data++; } message->size = ntohs(message->size); message->data = TR_malloc(message->size); } if (size >= message->size - message->size_done) { memcpy( message->data + message->size_done, data, message->size - message->size_done); size -= message->size - message->size_done; data += message->size - message->size_done; message->size_done = message->size; _message->ready = 1; if (size) { retval = TR_new(TR_RemoteData, data, size, _data->remote); } } else { memcpy(message->data + message->size_done, data, size); message->size_done += size; } TR_delete(_data); return retval; } static TR_RemoteData protocolRawCompose(void * _this, TR_ProtoMessage _message) { TR_ProtoMessageRaw message = (TR_ProtoMessageRaw)_message; TR_SizedData data; data = (TR_SizedData)TR_new(TR_RemoteData, NULL, 0, _message->remote); data->size = message->size + 2; data->data = TR_malloc(data->size); *(uint16_t *)data->data = htons(message->size); memcpy(data->data+2, message->data, message->size); return (TR_RemoteData)data; } TR_INIT_IFACE(TR_Class, protocolRawCtor, protocolRawDtor, NULL); TR_INIT_IFACE( TR_Protocol, protocolRawCreateMessage, protocolRawCreateMessage, protocolRawCreateMessage, protocolRawParse, protocolRawCompose); TR_CREATE_CLASS( TR_ProtocolRaw, TR_Protocol, NULL, TR_IF(TR_Class), TR_IF(TR_Protocol)); // vim: set ts=4 sw=4: