summaryrefslogblamecommitdiffstats
path: root/src/server/server.c
blob: e15249b709a254690e428ca2aaf0b05d13c50316 (plain) (tree)



















                                                               

                   
                      

                   

                    
                     
                       
 
                   
                  
                      

                   
 
          
 



                                              
 








                                                                                      

 
                          
 

                                            

 
                    
 


                            

 

                                



















                                                                   
                                       












                                                              
                                      

                  
                                  

                  
                                      







                                                                       

                                                           

                           



                                          

                    
                                 
                  
                           


                                      



                                           



                                         

             



                                                             
                     







                                                                                    
                                                                                     


                               
                    
 
/*
 * This file is part of the Distributed Network Block Device 3
 *
 * Copyright(c) 2011-2012 Johann Latocha <johann@latocha.de>
 *
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <signal.h>
#include <getopt.h>
#include <pthread.h>

#include "../types.h"
#include "../version.h"

#include "server.h"
#include "utils.h"
#include "hashtable.h"
#include "signal.h"
#include "net.h"

int _sock;

pthread_spinlock_t _spinlock;
char *_config_file_name = DEFAULT_CONFIG_FILE;

void dnbd3_print_help(char* argv_0)
{
    printf("Usage: %s [OPTIONS]...\n", argv_0);
    printf("Start the DNBD3 server\n");
    printf("-f or --file \t\t Configuration file (default /etc/dnbd3-server.conf)\n");
    printf("-n or --nodaemon \t\t Start server in foreground\n");
    printf("-r or --reload \t\t Reload configuration file\n");
    printf("-s or --stop \t\t Stop running dnbd3-server\n");
    printf("-h or --help \t\t Show this help text and quit\n");
    printf("-v or --version \t Show version and quit\n");
    exit(0);
}

void dnbd3_print_version()
{
    printf("Version: %s\n", VERSION_STRING);
    exit(0);
}

void dnbd3_cleanup()
{
    close(_sock);
    dnbd3_delete_pid_file();
    exit(EXIT_SUCCESS);
}

int main(int argc, char* argv[])
{
    int demonize = 1;
    int opt = 0;
    int longIndex = 0;
    static const char *optString = "f:nrshv?";
    static const struct option longOpts[] =
    {
    { "file", required_argument, NULL, 'f' },
    { "nodaemon", no_argument, NULL, 'n' },
    { "reload", no_argument, NULL, 'r' },
    { "stop", no_argument, NULL, 's' },
    { "help", no_argument, NULL, 'h' },
    { "version", no_argument, NULL, 'v' } };

    opt = getopt_long(argc, argv, optString, longOpts, &longIndex);

    while (opt != -1)
    {
        switch (opt)
        {
        case 'f':
            _config_file_name = optarg;
            break;
        case 'n':
            demonize = 0;
            break;
        case 'r':
            printf("INFO: Reloading configuration file...\n");
            dnbd3_send_signal(SIGHUP);
            return EXIT_SUCCESS;
        case 's':
            printf("INFO: Stopping running server...\n");
            dnbd3_send_signal(SIGTERM);
            return EXIT_SUCCESS;
        case 'h':
            dnbd3_print_help(argv[0]);
            break;
        case 'v':
            dnbd3_print_version();
            break;
        case '?':
            dnbd3_print_help(argv[0]);
        }
        opt = getopt_long(argc, argv, optString, longOpts, &longIndex);
    }

    if (demonize)
        daemon(1, 0);

    // load config file
    pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE);
    dnbd3_load_config(_config_file_name);

    // setup signal handler
    signal(SIGPIPE, dnbd3_handle_sigpipe);
    signal(SIGHUP, dnbd3_handle_sighup);
    signal(SIGTERM, dnbd3_handle_sigterm);
    signal(SIGINT, dnbd3_handle_sigterm);

    // setup network
    _sock = dnbd3_setup_socket();
    if (_sock < 0)
        exit(EXIT_FAILURE);
    struct sockaddr_in client;
    unsigned int len = sizeof(client);
    int fd;
    struct timeval timeout;
    timeout.tv_sec = SERVER_SOCKET_TIMEOUT;
    timeout.tv_usec = 0;

    dnbd3_write_pid_file(getpid());
    printf("INFO: Server is ready...\n");

    // main loop
    while (1)
    {
        fd = accept(_sock, (struct sockaddr*) &client, &len);
        if (fd < 0)
        {
            printf("ERROR: Accept failure\n");
            continue;
        }
        printf("INFO: Client: %s connected\n", inet_ntoa(client.sin_addr));

        setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout));
        setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout));

        // FIXME: catch SIGKILL/SIGTERM and close all socket before exit
        pthread_t thread;
        pthread_create(&(thread), NULL, dnbd3_handle_query, (void *) (uintptr_t) fd);
        pthread_detach(thread);
    }

    dnbd3_cleanup();
}