summaryrefslogblamecommitdiffstats
path: root/src/server/ipc.c
blob: 522c4cadb21d67c5fe21f55f192ae0abe4270100 (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 <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#include "ipc.h"
#include "config.h"
#include "server.h"
#include "utils.h"

void* dnbd3_ipc_receive()
{
    int server_sock, client_sock;
    struct sockaddr_un server, client;
    unsigned int len = sizeof(client);

    GSList *iterator = NULL;

    struct tm * timeinfo;
    char time_buff[64];

    // Create socket
    if ((server_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    {
        perror("ERROR: IPC socket");
        exit(EXIT_FAILURE);
    }

    server.sun_family = AF_UNIX;
    strcpy(server.sun_path, UNIX_SOCKET);
    unlink(UNIX_SOCKET);

    // Bind to socket
    if (bind(server_sock, &server, sizeof(server.sun_family) + strlen(server.sun_path)) < 0)
    {
        perror("ERROR: IPC bind");
        exit(EXIT_FAILURE);
    }

    // Listen on socket
    if (listen(server_sock, 5) < 0)
    {
        perror("ERROR: IPC listen");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        int cmd, num, i = 0;
        char buf[4096];

        // Accept connection
        if ((client_sock = accept(server_sock, &client, &len)) < 0)
        {
            perror("ERROR: IPC accept");
            exit(EXIT_FAILURE);
        }

        recv(client_sock, &cmd, sizeof(int), MSG_WAITALL);

        switch (cmd)
        {
        case IPC_EXIT:
            close(server_sock);
            dnbd3_cleanup();
            break;

        case IPC_RELOAD:
            printf("INFO: Reloading configuration...\n");
            dnbd3_reload_config(_config_file_name);
            break;

        case IPC_INFO:
            pthread_spin_lock(&_spinlock);
            num = g_slist_length(_dnbd3_clients) + _num_images +4;
            send(client_sock, &num, sizeof(int), MSG_WAITALL); // send number of lines to print

            sprintf(buf, "Exported images (atime, vid, rid, file):\n");
            strcat( buf, "========================================\n");
            send(client_sock, buf, sizeof(buf), MSG_WAITALL);
            for (i = 0; i < _num_images; i++)
            {
                timeinfo = localtime(&_images[i].atime);
                strftime (time_buff,64,"%d.%m.%y %H:%M:%S",timeinfo);
                sprintf(buf, "%s\t%i\t%i\t%s\n", time_buff, _images[i].vid, _images[i].rid,_images[i].file);
                send(client_sock, buf, sizeof(buf), MSG_WAITALL);
            }

            sprintf(buf, "\nNumber images: %Zu\n\n", _num_images);
            send(client_sock, buf, sizeof(buf), MSG_WAITALL);

            sprintf(buf, "Connected clients (ip, file):\n");
            strcat( buf, "=============================\n");
            send(client_sock, buf, sizeof(buf), MSG_WAITALL);
            for (iterator = _dnbd3_clients; iterator; iterator = iterator->next)
            {
                dnbd3_client_t *client = iterator->data;
                if (client->image)
                {
                    sprintf(buf, "%s\t%s\n", client->ip, client->image->file);
                    send(client_sock, buf, sizeof(buf), MSG_WAITALL);
                }
            }

            sprintf(buf, "\nNumber clients: %i\n\n", g_slist_length(_dnbd3_clients));
            send(client_sock, buf, sizeof(buf), MSG_WAITALL);

            pthread_spin_unlock(&_spinlock);
            close(client_sock);
            break;

        default:
            printf("ERROR: Unknown command: %i", cmd);
            break;

        }
    }
    close(server_sock);
}

void dnbd3_ipc_send(int cmd)
{
    int client_sock;
    struct sockaddr_un server;

    // Create socket
    if ((client_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    {
        perror("ERROR: IPC socket");
        exit(EXIT_FAILURE);
    }
    server.sun_family = AF_UNIX;
    strcpy(server.sun_path, UNIX_SOCKET);

    // Connect to server
    if (connect(client_sock, &server, sizeof(server.sun_family) + strlen(server.sun_path)) < 0)
    {
        perror("ERROR: IPC connect");
        exit(EXIT_FAILURE);
    }

    int i, num = 0;
    char buf[4096];

    switch (cmd)
    {
    case IPC_EXIT:
        send(client_sock, &cmd, sizeof(int), MSG_WAITALL);
        break;

    case IPC_RELOAD:
        send(client_sock, &cmd, sizeof(int), MSG_WAITALL);
        break;

    case IPC_INFO:
        send(client_sock, &cmd, sizeof(int), MSG_WAITALL);
        recv(client_sock, &num, sizeof(int), MSG_WAITALL);
        for (i = 0; i < num; i++)
        {
            if (recv(client_sock, &buf, sizeof(buf), MSG_WAITALL) > 0)
                printf("%s", buf);
        }
        break;

    default:
        printf("ERROR: Unknown command: %i", cmd);
        break;

    }
    close(client_sock);
}