added (single) client / server architecture

Wed, 05 Feb 2014 14:07:43 +0100

author
Mike Becker <universe@uap-core.de>
date
Wed, 05 Feb 2014 14:07:43 +0100
changeset 1
e5fbb8f9edbe
parent 0
98034084033f
child 2
0a08f79c320d

added (single) client / server architecture

conf.mk file | annotate | diff | comparison | revisions
src/Makefile file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
src/network.c file | annotate | diff | comparison | revisions
src/network.h file | annotate | diff | comparison | revisions
src/terminal-chess.h file | annotate | diff | comparison | revisions
     1.1 --- a/conf.mk	Thu Jan 23 14:45:34 2014 +0100
     1.2 +++ b/conf.mk	Wed Feb 05 14:07:43 2014 +0100
     1.3 @@ -31,7 +31,7 @@
     1.4  RM      = rm
     1.5  
     1.6  # build related
     1.7 -BIN     = c2html
     1.8 +BIN     = terminal-chess
     1.9  CC      = gcc
    1.10  CFLAGS  = -g -O2 -std=gnu99 -Wall -Werror -pedantic
    1.11  LD      = gcc
     2.1 --- a/src/Makefile	Thu Jan 23 14:45:34 2014 +0100
     2.2 +++ b/src/Makefile	Wed Feb 05 14:07:43 2014 +0100
     2.3 @@ -29,6 +29,7 @@
     2.4  include ../conf.mk
     2.5  
     2.6  SRC  = main.c
     2.7 +SRC += network.c
     2.8  
     2.9  OBJ = $(SRC:%.c=../build/%$(OBJ_EXT))
    2.10  
     3.1 --- a/src/main.c	Thu Jan 23 14:45:34 2014 +0100
     3.2 +++ b/src/main.c	Wed Feb 05 14:07:43 2014 +0100
     3.3 @@ -27,9 +27,98 @@
     3.4   *
     3.5   */
     3.6  
     3.7 -#include <stdlib.h>
     3.8 +#include "terminal-chess.h"
     3.9 +#include <string.h>
    3.10 +
    3.11 +int get_settings(int argc, char **argv, Settings *settings) {
    3.12 +    char *valid;
    3.13 +    
    3.14 +    for (char opt ; (opt = getopt(argc, argv, "hp:")) != -1 ;) {
    3.15 +        switch (opt) {
    3.16 +            case 'p':
    3.17 +                if (strtol(optarg, &valid, 10) < 1025 || *valid != '\0') {
    3.18 +                    fprintf(stderr,
    3.19 +                        "Invalid port number (%s) - choose a number > 1024\n",
    3.20 +                        optarg);
    3.21 +                    return 1;
    3.22 +                } else {
    3.23 +                    settings->port = optarg;
    3.24 +                }
    3.25 +                break;
    3.26 +            case 'h':
    3.27 +            case '?':
    3.28 +                settings->printhelp = 1;
    3.29 +                break;
    3.30 +        }
    3.31 +    }
    3.32 +    
    3.33 +    if (optind == argc - 1) {
    3.34 +        settings->serverhost = argv[optind];
    3.35 +    } else if (optind < argc - 1) {
    3.36 +        fprintf(stderr, "Too many arguments\n");
    3.37 +        return 1;
    3.38 +    }
    3.39 +    
    3.40 +    return 0;
    3.41 +}
    3.42 +
    3.43 +Settings default_settings() {
    3.44 +    Settings settings;
    3.45 +    memset(&settings, 0, sizeof(Settings));
    3.46 +    settings.port = "27015";
    3.47 +    return settings;
    3.48 +}
    3.49 +
    3.50 +int cleanup(Settings *settings, int exitcode) {
    3.51 +    if (settings->server) {
    3.52 +        if (net_destroy(settings->server)) {
    3.53 +            perror("Server shutdown failed");
    3.54 +        }
    3.55 +    }
    3.56 +    
    3.57 +    return exitcode;
    3.58 +}
    3.59  
    3.60  int main(int argc, char **argv) {
    3.61 -    return EXIT_SUCCESS;
    3.62 +    
    3.63 +    Settings settings = default_settings();
    3.64 +    get_settings(argc, argv, &settings);
    3.65 +    
    3.66 +    if (settings.printhelp) {
    3.67 +        printf(
    3.68 +            "Usage: %s [OPTION]... [HOST]\n"
    3.69 +            "Starts/joins a network chess game\n\n"
    3.70 +            "  -h            This help page\n"
    3.71 +            "  -p            TCP port to use (default: 27015)\n",
    3.72 +            argv[0]);
    3.73 +        return EXIT_SUCCESS;
    3.74 +    }
    3.75 +    
    3.76 +    Server server;
    3.77 +    settings.server = &server;
    3.78 +    
    3.79 +    if (is_server(&settings)) {
    3.80 +        if (net_find(&server, settings.serverhost, settings.port)) {
    3.81 +            perror("Can't find server");
    3.82 +            return cleanup(&settings, EXIT_FAILURE);
    3.83 +        }
    3.84 +        
    3.85 +        if (net_connect(&server)) {
    3.86 +            perror("Can't connect to server");
    3.87 +            return cleanup(&settings, EXIT_FAILURE);
    3.88 +        }
    3.89 +    } else {
    3.90 +        if (net_create(&server, settings.port)) {
    3.91 +            perror("Server creation failed");
    3.92 +            return cleanup(&settings, EXIT_FAILURE);
    3.93 +        }
    3.94 +        
    3.95 +        if (net_listen(&server)) {
    3.96 +            perror("Listening for client failed");
    3.97 +            return cleanup(&settings, EXIT_FAILURE);
    3.98 +        }
    3.99 +    }
   3.100 +    
   3.101 +    return cleanup(&settings, EXIT_SUCCESS);
   3.102  }
   3.103  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/network.c	Wed Feb 05 14:07:43 2014 +0100
     4.3 @@ -0,0 +1,115 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2014 Mike Becker. All rights reserved.
     4.8 + *
     4.9 + * Redistribution and use in source and binary forms, with or without
    4.10 + * modification, are permitted provided that the following conditions are met:
    4.11 + *
    4.12 + *   1. Redistributions of source code must retain the above copyright
    4.13 + *      notice, this list of conditions and the following disclaimer.
    4.14 + *
    4.15 + *   2. Redistributions in binary form must reproduce the above copyright
    4.16 + *      notice, this list of conditions and the following disclaimer in the
    4.17 + *      documentation and/or other materials provided with the distribution.
    4.18 + *
    4.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    4.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    4.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    4.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    4.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    4.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    4.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    4.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    4.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    4.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    4.29 + * POSSIBILITY OF SUCH DAMAGE.
    4.30 + *
    4.31 + */
    4.32 +
    4.33 +#include <stdlib.h>
    4.34 +#include <string.h>
    4.35 +#include "network.h"
    4.36 +
    4.37 +int server_bind(Server *server) {
    4.38 +    server->fd = socket(server->info->ai_family,
    4.39 +        server->info->ai_socktype, server->info->ai_protocol);
    4.40 +    if (server->fd > -1) {
    4.41 +        int true = 1;
    4.42 +        setsockopt(server->fd, SOL_SOCKET, SO_REUSEADDR, &true, sizeof(int));
    4.43 +        if (bind(server->fd,
    4.44 +                server->info->ai_addr, server->info->ai_addrlen)) {
    4.45 +            server->fd = -1;
    4.46 +            return 1;
    4.47 +        } else {
    4.48 +            return 0;
    4.49 +        }
    4.50 +    } else {
    4.51 +        return 1;
    4.52 +    }
    4.53 +}
    4.54 +
    4.55 +int net_create(Server *server, char* port) {
    4.56 +    return net_find(server, "localhost", port) || server_bind(server);
    4.57 +}
    4.58 +
    4.59 +int getaddrinfo_intrnl(char *host, char *port, struct addrinfo **info) {
    4.60 +    struct addrinfo hints;
    4.61 +    memset(&hints, 0, sizeof(hints));
    4.62 +    hints.ai_socktype = SOCK_STREAM;
    4.63 +    hints.ai_protocol = IPPROTO_TCP;
    4.64 +    
    4.65 +    return getaddrinfo(host, port, &hints, info);
    4.66 +}
    4.67 +
    4.68 +int net_find(Server *server, char *host, char* port) {
    4.69 +    memset(server, 0, sizeof(Server));
    4.70 +    server->fd = -1;
    4.71 +    
    4.72 +    return getaddrinfo_intrnl(host, port, &(server->info));
    4.73 +}
    4.74 +
    4.75 +int net_listen(Server *server) {
    4.76 +    listen(server->fd, 1);
    4.77 +    Client* client = calloc(1, sizeof(Client));
    4.78 +    client->fd = -1;
    4.79 +    server->client = client;
    4.80 +    
    4.81 +    client->fd = accept(server->fd,
    4.82 +        &(client->address), &(client->address_len));
    4.83 +    
    4.84 +    return client->fd == -1;
    4.85 +}
    4.86 +
    4.87 +int net_connect(Server *server) {
    4.88 +    struct addrinfo *info;
    4.89 +    if (getaddrinfo_intrnl("localhost", NULL, &info)) {
    4.90 +        return 1;
    4.91 +    }
    4.92 +    
    4.93 +    Client* client = calloc(1, sizeof(Client));
    4.94 +    client->fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
    4.95 +    server->client = client;
    4.96 +    
    4.97 +    freeaddrinfo(info);
    4.98 +    if (client->fd == -1) {
    4.99 +        return 1;
   4.100 +    }
   4.101 +    
   4.102 +    return connect(client->fd, server->info->ai_addr, server->info->ai_addrlen);
   4.103 +}
   4.104 +
   4.105 +int net_destroy(Server *server) {
   4.106 +    if (server->info) {
   4.107 +        freeaddrinfo(server->info);
   4.108 +    }
   4.109 +    if (server->client) {
   4.110 +        shutdown(server->client->fd, SHUT_RDWR);
   4.111 +        free(server->client);
   4.112 +    }
   4.113 +    if (server->fd > -1) {
   4.114 +        return shutdown(server->fd, SHUT_RDWR);
   4.115 +    }
   4.116 +    
   4.117 +    return EXIT_SUCCESS;
   4.118 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/network.h	Wed Feb 05 14:07:43 2014 +0100
     5.3 @@ -0,0 +1,65 @@
     5.4 +/*
     5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     5.6 + *
     5.7 + * Copyright 2014 Mike Becker. All rights reserved.
     5.8 + *
     5.9 + * Redistribution and use in source and binary forms, with or without
    5.10 + * modification, are permitted provided that the following conditions are met:
    5.11 + *
    5.12 + *   1. Redistributions of source code must retain the above copyright
    5.13 + *      notice, this list of conditions and the following disclaimer.
    5.14 + *
    5.15 + *   2. Redistributions in binary form must reproduce the above copyright
    5.16 + *      notice, this list of conditions and the following disclaimer in the
    5.17 + *      documentation and/or other materials provided with the distribution.
    5.18 + *
    5.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    5.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    5.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    5.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    5.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    5.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    5.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    5.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    5.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    5.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    5.29 + * POSSIBILITY OF SUCH DAMAGE.
    5.30 + *
    5.31 + */
    5.32 +
    5.33 +#ifndef TCHESS_NETWORK_H
    5.34 +#define	TCHESS_NETWORK_H
    5.35 +
    5.36 +#include <sys/socket.h>
    5.37 +#include <netdb.h>
    5.38 +
    5.39 +#ifdef	__cplusplus
    5.40 +extern "C" {
    5.41 +#endif
    5.42 +
    5.43 +typedef struct {
    5.44 +    int fd;
    5.45 +    struct sockaddr address;
    5.46 +    socklen_t address_len;
    5.47 +} Client;
    5.48 +
    5.49 +typedef struct {
    5.50 +    int fd;
    5.51 +    struct addrinfo* info;
    5.52 +    Client *client;
    5.53 +} Server;
    5.54 +
    5.55 +int net_create(Server *server, char* port);
    5.56 +int net_find(Server *server, char* host, char* port);
    5.57 +
    5.58 +int net_listen(Server *server);
    5.59 +int net_destroy(Server *server);
    5.60 +int net_connect(Server *server);
    5.61 +
    5.62 +
    5.63 +#ifdef	__cplusplus
    5.64 +}
    5.65 +#endif
    5.66 +
    5.67 +#endif	/* TCHESS_NETWORK_H */
    5.68 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/terminal-chess.h	Wed Feb 05 14:07:43 2014 +0100
     6.3 @@ -0,0 +1,56 @@
     6.4 +/*
     6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     6.6 + *
     6.7 + * Copyright 2014 Mike Becker. All rights reserved.
     6.8 + *
     6.9 + * Redistribution and use in source and binary forms, with or without
    6.10 + * modification, are permitted provided that the following conditions are met:
    6.11 + *
    6.12 + *   1. Redistributions of source code must retain the above copyright
    6.13 + *      notice, this list of conditions and the following disclaimer.
    6.14 + *
    6.15 + *   2. Redistributions in binary form must reproduce the above copyright
    6.16 + *      notice, this list of conditions and the following disclaimer in the
    6.17 + *      documentation and/or other materials provided with the distribution.
    6.18 + *
    6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    6.29 + * POSSIBILITY OF SUCH DAMAGE.
    6.30 + *
    6.31 + */
    6.32 +
    6.33 +#include <stdlib.h>
    6.34 +#include <stdio.h>
    6.35 +#include <getopt.h>
    6.36 +#include "network.h"
    6.37 +
    6.38 +#ifndef TERMINAL_CHESS_H
    6.39 +#define	TERMINAL_CHESS_H
    6.40 +
    6.41 +#ifdef	__cplusplus
    6.42 +extern "C" {
    6.43 +#endif
    6.44 +
    6.45 +typedef struct {
    6.46 +    int printhelp;
    6.47 +    char* port;
    6.48 +    char* serverhost; /* NULL, if we are about to start a server */
    6.49 +    Server *server;
    6.50 +} Settings;
    6.51 +
    6.52 +#define is_server(settings) ((settings)->serverhost)
    6.53 +
    6.54 +#ifdef	__cplusplus
    6.55 +}
    6.56 +#endif
    6.57 +
    6.58 +#endif	/* TERMINAL_CHESS_H */
    6.59 +

mercurial