/* usock.h - Implementation of usock.  */

/* Copyright (C) 2022, 2023 Mohammad-Reza Nabipoor.  */

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef USOCK_H
#define USOCK_H

#include <config.h>

#include "usock-buf.h"

// Pre-defined channels
// (Channel is a 7-bit unsigned number)
#define USOCK_CHAN_IN_CODE 0x01
#define USOCK_CHAN_IN_CMD 0x02
#define USOCK_CHAN_OUT_OUT 0x01
#define USOCK_CHAN_OUT_VU 0x02
#define USOCK_CHAN_OUT_PDISAS 0x03 /* Poke disasm.  */
#define USOCK_CHAN_OUT_TREEVU 0x04
#define USOCK_CHAN_OUT_AUTOCMPL 0x05
#define USOCK_CHAN_OUT_CDISAS 0x06 /* CPU disasm.  */

struct usock;

// Allocates a new server over unix domain socket at PATH.
struct usock *usock_new (const char *path);

void usock_free (struct usock *u);

#define USOCK_SERVE_OK 0
#define USOCK_SERVE_NOK 1

// Run the server loop.
// This should run on a separate thread.
// On success return USOCK_SERVE_OK, otherwise USOCK_SERVE_NOK.
// On failure, two functions are allowed to be called:
//   - usock_serve_error to retrieve the error message
//   - usock_free to deallocate the server
int usock_serve (struct usock *u);

// Return a pointer to a NULL-terminated error message.
// Invocation of this function is only valid if usock_serve is done.
const char *usock_serve_error (struct usock *u);

// Wake up the server thread to react to new data.
void usock_notify (struct usock *u);

// Signal the server thread to finish the server loop.
void usock_done (struct usock *u);

// Get all received data over chained buffers.
// This call is blocking and will block the calling thread.
struct usock_buf *usock_in (struct usock *u);

// Put DATA with length LEN in server's queue to be dispatched over
// channel CHAN.
// Non-zero KIND will be encoded as ULEB128 number before DATA.
// This call is non-blocking.
void usock_out (struct usock *u, uint8_t chan, uint32_t kind, const void *data,
                size_t len);

// Like `usock_out' but with a printf-like interface.
// On success return the number of characters sent (excluding the null byte).
// On failure return -1.
int usock_out_printf (struct usock *u, uint8_t chan, uint32_t kind,
                      const char *fmt, ...)
    __attribute__ ((format (printf, 4, 5)));

#endif
