You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
3.7 KiB
183 lines
3.7 KiB
/**
|
|
* \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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
|
|
#include "trbase.h"
|
|
#include "trevent.h"
|
|
#include "trio.h"
|
|
|
|
#include "tr/io_handler.h"
|
|
#include "tr/comm_end_point.h"
|
|
#include "tr/interface/comm_end_point.h"
|
|
|
|
static
|
|
int
|
|
ioHandlerCtor(void * _this, va_list * params)
|
|
{
|
|
TR_PARENTCALL(TR_IoHandler, _this, TR_Class, ctor, params);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ioHandlerDtor(void * _this) {}
|
|
|
|
static
|
|
TR_EventDone
|
|
ioHandlerRead(void * _this, TR_Event event)
|
|
{
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject;
|
|
TR_Event revent;
|
|
TR_RemoteData data;
|
|
|
|
switch (TR_commEndPointRead(endpoint, &data)) {
|
|
case FALSE: // EAGAIN
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_READ_BLOCK,
|
|
NULL);
|
|
break;
|
|
|
|
case -1: // error
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_CLOSE,
|
|
NULL);
|
|
break;
|
|
|
|
default:
|
|
case -2: // remote close
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_SHUT_READ,
|
|
NULL);
|
|
break;
|
|
|
|
case -3: // read limit
|
|
return TR_EVENT_DONE;
|
|
|
|
case TRUE:
|
|
if (event->subject->fin) {
|
|
TR_delete(data);
|
|
return TR_EVENT_DONE;
|
|
}
|
|
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_NEW_DATA,
|
|
data);
|
|
break;
|
|
}
|
|
|
|
TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent);
|
|
|
|
return TR_EVENT_DONE;
|
|
}
|
|
|
|
static
|
|
TR_EventDone
|
|
ioHandlerWrite(void * _this, TR_Event event)
|
|
{
|
|
TR_Event revent = NULL;
|
|
TR_CommEndPoint endpoint = (TR_CommEndPoint)event->subject;
|
|
size_t written;
|
|
|
|
switch (TR_cepWriteBuffered(endpoint, &written)) {
|
|
case FALSE: // EAGAIN
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_WRITE_BLOCK,
|
|
NULL);
|
|
break;
|
|
|
|
case -1: // FAILURE
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_CLOSE,
|
|
NULL);
|
|
break;
|
|
|
|
case -2: // remote close
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_SHUT_WRITE,
|
|
NULL);
|
|
break;
|
|
|
|
case -3: // remote end not ready
|
|
break;
|
|
|
|
case -4: // no more data to send
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_DATA_END,
|
|
NULL);
|
|
break;
|
|
|
|
default:
|
|
// TODO This still looks wrong...
|
|
if (TRUE == endpoint->do_close) {
|
|
revent = TR_eventSubjectEmit(
|
|
event->subject,
|
|
TR_CEP_EVENT_CLOSE,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
endpoint->write_buffer_size -= written;
|
|
|
|
if (revent) {
|
|
TR_eventHandlerIssueEvent((TR_EventHandler)_this, revent);
|
|
}
|
|
|
|
return TR_EVENT_DONE;
|
|
}
|
|
|
|
static
|
|
void
|
|
ioHandlerCvInit(TR_class_ptr cls)
|
|
{
|
|
TR_EVENT_HANDLER_SET_METHOD(
|
|
cls,
|
|
TR_CommEndPoint,
|
|
TR_CEP_EVENT_DO_READ,
|
|
ioHandlerRead);
|
|
TR_EVENT_HANDLER_SET_METHOD(
|
|
cls,
|
|
TR_CommEndPoint,
|
|
TR_CEP_EVENT_DO_WRITE,
|
|
ioHandlerWrite);
|
|
}
|
|
|
|
TR_INIT_HANDLER(TR_IoHandler);
|
|
TR_INIT_IFACE(TR_Class, ioHandlerCtor, ioHandlerDtor, NULL);
|
|
TR_CREATE_CLASS(
|
|
TR_IoHandler,
|
|
TR_EventHandler,
|
|
ioHandlerCvInit,
|
|
TR_IF(TR_Class)) = {
|
|
{ TR_HANDLER_CVARS(TR_IoHandler) }
|
|
};
|
|
|
|
// vim: set ts=4 sw=4:
|