i_socket.c 2.66 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);

extern inline int TR_socketBindAction(void *);
extern inline int TR_socketConnectAction(void *);

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:
			// case EWOULDBLOCK: // is the same value as EAGAIN
				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);

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

			case EAGAIN:
			//case EWOULDBLOCK: // is the same value as EAGAIN
                return FALSE;

            default:
            case ECONNRESET:
            case EPIPE:
                // this is a remote close...
                return -2;
        }
    } else if (size == 0) {
		/*
		 * It might happen that a write returns 0. In that case the remote
		 * end was not ready to accept the data. This might be handled
		 * differently by the managing code so I return a separate value
		 * for this.
		 */
		return -3;
	}

    return size;
}

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