src/network.c

Mon, 21 Mar 2016 20:35:58 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 21 Mar 2016 20:35:58 +0100
changeset 56
11b57a15d11a
parent 55
54ea19938d57
child 59
3fa1de896666
permissions
-rw-r--r--

fixed hypthetical bug, where the client address is not correctly retrieved by accept()

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2016 Mike Becker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <stdlib.h>
#include <string.h>
#include "network.h"

#define new_socket() socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

int net_create(Server *server, char* port) {
    server->info = NULL;
    
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(atoi(port));
    
    server->fd = new_socket();
    if (server->fd > -1) {
        int true = 1;
        setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(int));
        if (bind(server->fd, (struct sockaddr*)&addr, sizeof(addr))) {
            server->fd = -1;
            return 1;
        } else {
            return 0;
        }
    } else {
        return 1;
    }
}

static int getaddrinfo_intrnl(char *host, char *port, struct addrinfo **info) {
    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    
    return getaddrinfo(host, port, &hints, info);
}

int net_find(Server *server, char *host, char* port) {
    memset(server, 0, sizeof(Server));
    server->fd = -1;
    
    return getaddrinfo_intrnl(host, port, &(server->info));
}

int net_listen(Server *server) {
    listen(server->fd, 1);
    Client* client = malloc(sizeof(Client));
    client->fd = -1;
    client->address_len = sizeof(client->address);
    server->client = client;
    
    client->fd = accept(server->fd,
        &(client->address), &(client->address_len));
    
    return client->fd == -1;
}

int net_connect(Server *server) {
    
    Client* client = calloc(1, sizeof(Client));
    client->fd = -1;
    server->fd = new_socket();
    server->client = client;
    
    if (server->fd == -1) {
        return 1;
    }
    
    return connect(server->fd, server->info->ai_addr, server->info->ai_addrlen);
}

int net_destroy(Server *server) {
    if (server->info) {
        freeaddrinfo(server->info);
    }
    if (server->client) {
        shutdown(server->client->fd, SHUT_RDWR);
        free(server->client);
    }
    if (server->fd > -1) {
        return shutdown(server->fd, SHUT_RDWR);
    }
    
    return EXIT_SUCCESS;
}

void net_send_code(int socket, uint8_t code) {
    send(socket, &code, sizeof(uint8_t), 0);
}

void net_send_data(int socket, uint8_t code, void *data, size_t len) {
    uint8_t pkg[len+1];
    pkg[0] = code;
    memcpy(pkg+1, data, len);
    send(socket, pkg, len+1, 0);
}

uint8_t net_recieve_code(int socket) {
    uint8_t code;
    if (recv(socket, &code, sizeof(code), 0) == sizeof(code)) {
        return code;
    } else {
        return NETCODE_CONNLOST;
    }
}

void net_recieve_data(int socket, void *data, size_t len) {
    recv(socket, data, len, MSG_WAITALL);
}

mercurial