#define _GNU_SOURCE
#include "channel.h"
#include "exchange.h"
#include <stdlib.h>
#include <sys/shm.h>

int main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "usage: %s SOCKET\n", argv[0]);
        return EXIT_FAILURE;
    }
    int result = EXIT_FAILURE, listener = -1, peer = -1;
    int initialized = 0, published = 0;
    int id = shmget(IPC_PRIVATE, sizeof(struct exchange), IPC_CREAT | 0600);
    struct exchange *box = (void *)-1;
    if (id == -1)
        goto out;
    printf("shmid=%d\n", id);
    fflush(stdout);
    box = shmat(id, NULL, 0);
    if (box == (void *)-1 || exchange_init(box) == -1)
        goto out;
    initialized = 1;
    listener = channel_open(argv[1], 1);
    if (listener == -1)
        goto out;
    peer = channel_accept(listener);
    if (peer == -1)
        goto out;
    published = 1;
    if (channel_send(peer, &id, sizeof(id)) == -1 ||
        exchange_server(box) == -1 || channel_finished(peer) == -1)
        goto out;
    puts("exchange complete");
    result = EXIT_SUCCESS;
out:
    if (result != EXIT_SUCCESS)
        perror("System V server");
    if (initialized && (!published || result == EXIT_SUCCESS) &&
        exchange_destroy(box) == -1) {
        perror("sem_destroy");
        result = EXIT_FAILURE;
    }
    if (box != (void *)-1 && shmdt(box) == -1) {
        perror("shmdt");
        result = EXIT_FAILURE;
    }
    if (id != -1 && shmctl(id, IPC_RMID, NULL) == -1) {
        perror("IPC_RMID");
        result = EXIT_FAILURE;
    }
    if (peer != -1 && close(peer) == -1) {
        perror("peer close");
        result = EXIT_FAILURE;
    }
    if (listener != -1) {
        if (channel_remove(listener, argv[1]) == -1) {
            perror("listener cleanup");
            result = EXIT_FAILURE;
        }
    }
    return result;
}
