i_socket.c 2.5 KB
/**
 * \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 <errno.h>

#include "tr/interface/socket.h"
#include "tr/remote_data.h"
#include "trbase.h"

TR_CREATE_INTERFACE(TR_Socket, 4);

int
TR_socketBindAction(void * _this)
{
	int callret;

	TR_RETCALL(_this, TR_Socket, bind, callret);

	return callret;
}

int
TR_socketConnectAction(void * _this)
{
	int callret;

	TR_RETCALL(_this, TR_Socket, connect, callret);

	return callret;
}

TR_RemoteData
TR_socketRecv(void * _this, size_t size)
{
	TR_RemoteData remote_data;

	TR_RETCALL(_this, TR_Socket, recv, remote_data, size);

    if (! remote_data) {
        switch (errno) {
			case (EAGAIN|EWOULDBLOCK):
				TR_delete(remote_data);
                return TR_emptyRemoteData;

            case EINTR:
            case ENOMEM:
                // these are fatal and should lead to a shutown
                // of the whole application...
				TR_delete(remote_data);
                return NULL;

            default:
				TR_delete(remote_data);
                return NULL;
        }
    } else if (((TR_SizedData)remote_data)->size == 0) {
        // this is a remote close...
		TR_delete(remote_data);
        return (void*)-1;
    }

    return remote_data;
}

ssize_t
TR_socketSend(void * _this, TR_RemoteData data)
{
	ssize_t size;

	TR_RETCALL(_this, TR_Socket, send, size, data);
	TR_delete(data);

    if (size < 0) {
        switch (errno) {
            case EINTR:
            case ENOMEM:
                // these are fatal and should lead to a shutown
                // of the whole application...
                return 0;

            case (EAGAIN|EWOULDBLOCK):
                return -1;

            case ECONNRESET:
                // this is a remote close...
                return -2;

            default:
                return -2;
        }
    }

    return size;
}

// vim: set ts=4 sw=4: