/*
 * pipe.h
 *
 * Copyright (C) 2013 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _PIPE_H_
#define _PIPE_H_

#include <lock.h>
#include <object.h>
#include <sdk/pipe.h>
#include <thread.h>

#define PIPE_BLOCK_SIZE 1024
#define MAX_PIPE_BLOCKS 1024

#define PIPE_MESSAGE (1 << 0)

enum
{
    PIPELINE_IDLE,
    PIPELINE_ACCEPTING,
    PIPELINE_CONNECTING,
    PIPELINE_FAILED,
};

typedef struct
{
    object_t header;
    dword_t flags;
    lock_t lock;
    dword_t bytes_ready;
    list_entry_t fifo;
} pipe_t;

typedef struct
{
    list_entry_t link;
    dword_t start, end;
    bool_t full;
    byte_t data[PIPE_BLOCK_SIZE];
} pipe_fifo_entry_t;

typedef struct
{
    list_entry_t link;
    size_t size;
    byte_t data[VARIABLE_SIZE];
} pipe_message_entry_t;

typedef struct
{
    object_t header;
    dword_t flags;
    lock_t lock;
    uintptr_t status;
    dword_t server_pid;
    dword_t client_pid;
    pipe_t *request_pipe;
    pipe_t *response_pipe;
    dword_t last_error;
} pipeline_t;

static inline void init_pipe(pipe_t *pipe, dword_t flags)
{
    pipe->flags = flags;
    lock_init(&pipe->lock);
    list_init(&pipe->fifo);
}

dword_t read_pipe(pipe_t *pipe, void *buffer, size_t *size, dword_t timeout);
dword_t write_pipe(pipe_t *pipe, const void *buffer, size_t size);
void pipe_cleanup(object_t *obj);
dword_t pipe_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);

#endif
