/* This is a simple TCP server that listens on port 1234 and provides lists
 * of files to clients, using a protocol defined in file_server.proto.
 *
 * It directly deserializes and serializes messages from network, minimizing
 * memory use.
 * 
 * For flexibility, this example is implemented using posix api.
 * In a real embedded system you would typically use some other kind of
 * a communication and filesystem layer.
 */

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>

#include <pb_encode.h>
#include <pb_decode.h>

#include "fileproto.pb.h"
#include "common.h"

/* This callback function will be called during the encoding.
 * It will write out any number of FileInfo entries, without consuming unnecessary memory.
 * This is accomplished by fetching the filenames one at a time and encoding them
 * immediately.
 */
bool ListFilesResponse_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
{
    PB_UNUSED(istream);
    if (ostream != NULL && field->tag == ListFilesResponse_file_tag)
    {
        DIR *dir = *(DIR**)field->pData;
        struct dirent *file;
        FileInfo fileinfo = {};

        while ((file = readdir(dir)) != NULL)
        {
            fileinfo.inode = file->d_ino;
            strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name));
            fileinfo.name[sizeof(fileinfo.name) - 1] = '\0';

            /* This encodes the header for the field, based on the constant info
            * from pb_field_t. */
            if (!pb_encode_tag_for_field(ostream, field))
                return false;

            /* This encodes the data for the field, based on our FileInfo structure. */
            if (!pb_encode_submessage(ostream, FileInfo_fields, &fileinfo))
                return false;
        }

        /* Because the main program uses pb_encode_delimited(), this callback will be
        * called twice. Rewind the directory for the next call. */
        rewinddir(dir);
    }

    return true;
}

/* Handle one arriving client connection.
 * Clients are expected to send a ListFilesRequest, terminated by a '0'.
 * Server will respond with a ListFilesResponse message.
 */
void handle_connection(int connfd)
{
    DIR *directory = NULL;
    
    /* Decode the message from the client and open the requested directory. */
    {
        ListFilesRequest request = {};
        pb_istream_t input = pb_istream_from_socket(connfd);
        
        if (!pb_decode_delimited(&input, ListFilesRequest_fields, &request))
        {
            printf("Decode failed: %s\n", PB_GET_ERROR(&input));
            return;
        }
        
        directory = opendir(request.path);
        printf("Listing directory: %s\n", request.path);
    }
    
    /* List the files in the directory and transmit the response to client */
    {
        ListFilesResponse response = {};
        pb_ostream_t output = pb_ostream_from_socket(connfd);
        
        if (directory == NULL)
        {
            perror("opendir");
            
            /* Directory was not found, transmit error status */
            response.has_path_error = true;
            response.path_error = true;
        }
        else
        {
            /* Directory was found, transmit filenames */
            response.has_path_error = false;
            response.file = directory;
        }
        
        if (!pb_encode_delimited(&output, ListFilesResponse_fields, &response))
        {
            printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
        }
    }
    
    if (directory != NULL)
        closedir(directory);
}

int main(int argc, char **argv)
{
    int listenfd, connfd;
    struct sockaddr_in servaddr;
    int reuse = 1;
    
    /* Listen on localhost:1234 for TCP connections */
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    servaddr.sin_port = htons(1234);
    if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0)
    {
        perror("bind");
        return 1;
    }
    
    if (listen(listenfd, 5) != 0)
    {
        perror("listen");
        return 1;
    }
    
    for(;;)
    {
        /* Wait for a client */
        connfd = accept(listenfd, NULL, NULL);
        
        if (connfd < 0)
        {
            perror("accept");
            return 1;
        }
        
        printf("Got connection.\n");
        
        handle_connection(connfd);
        
        printf("Closing connection.\n");
        
        close(connfd);
    }
    
    return 0;
}
