167 lines
3.5 KiB
C
167 lines
3.5 KiB
C
#include "spdk/stdinc.h"
|
|
#include "spdk/env.h"
|
|
#include "spdk/jsonrpc.h"
|
|
#include "spdk/thread.h"
|
|
#include "bdev_longhorn_remote.h"
|
|
|
|
struct tcp_client_handler_entry {
|
|
char *command;
|
|
int32_t id;
|
|
|
|
void *arg;
|
|
|
|
json_remote_response_handler_fn fn;
|
|
|
|
TAILQ_ENTRY(tcp_client_handler_entry) entries;
|
|
};
|
|
|
|
|
|
struct tcp_client_entry {
|
|
const char *addr;
|
|
struct spdk_jsonrpc_client *client;
|
|
|
|
TAILQ_HEAD(, tcp_client_handler_entry) handlers;
|
|
|
|
TAILQ_ENTRY(tcp_client_entry) entries;
|
|
};
|
|
|
|
static TAILQ_HEAD(, tcp_client_entry) tcp_clients = TAILQ_HEAD_INITIALIZER(tcp_clients);
|
|
static struct spdk_poller *poller = NULL;
|
|
|
|
static void handler_free(struct tcp_client_handler_entry *handler) {
|
|
if (handler) {
|
|
free(handler->command);
|
|
free(handler);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
static void remote_client_handle(struct tcp_client_entry *entry)
|
|
{
|
|
struct spdk_jsonrpc_client_response *response = NULL;
|
|
int32_t id = 0;
|
|
struct tcp_client_handler_entry *handler = NULL;
|
|
struct tcp_client_handler_entry *next = NULL;
|
|
|
|
response = spdk_jsonrpc_client_get_response(entry->client);
|
|
|
|
if (spdk_json_number_to_int32(response->id, &id) != 0) {
|
|
printf("Unable to decode TCP client message.\n");
|
|
|
|
spdk_jsonrpc_client_free_response(response);
|
|
|
|
return;
|
|
}
|
|
|
|
handler = TAILQ_FIRST(&entry->handlers);
|
|
|
|
while (handler != NULL) {
|
|
next = TAILQ_NEXT(handler, entries);
|
|
|
|
if (handler->id == id) {
|
|
(*(handler->fn))(entry->addr, handler->command, id,
|
|
response->result, response->error,
|
|
handler->arg);
|
|
|
|
TAILQ_REMOVE(&entry->handlers, handler, entries);
|
|
handler_free(handler);
|
|
|
|
break;
|
|
}
|
|
|
|
handler = next;
|
|
}
|
|
|
|
spdk_jsonrpc_client_free_response(response);
|
|
}
|
|
|
|
|
|
static int remote_client_poll(void *arg)
|
|
{
|
|
struct tcp_client_entry *entry = NULL;
|
|
struct tcp_client_entry *next = NULL;
|
|
int error = 0;
|
|
|
|
entry = TAILQ_FIRST(&tcp_clients);
|
|
|
|
while (entry != NULL) {
|
|
next = TAILQ_NEXT(entry, entries);
|
|
|
|
error = spdk_jsonrpc_client_poll(entry->client, 0);
|
|
|
|
if (error > 0) {
|
|
remote_client_handle(entry);
|
|
} else if (error == -EIO) {
|
|
}
|
|
|
|
entry = next;
|
|
}
|
|
|
|
return SPDK_POLLER_BUSY;
|
|
}
|
|
|
|
static struct tcp_client_entry *
|
|
json_client_lookup(const char *addr) {
|
|
struct tcp_client_entry *entry = NULL;
|
|
|
|
TAILQ_FOREACH(entry, &tcp_clients, entries) {
|
|
if (strcmp(addr, entry->addr) == 0) {
|
|
return entry;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int json_remote_client(const char *addr)
|
|
{
|
|
struct spdk_jsonrpc_client *client = NULL;
|
|
struct tcp_client_entry *entry = json_client_lookup(addr);
|
|
|
|
if (entry == NULL) {
|
|
client = spdk_jsonrpc_client_connect(addr, AF_INET);
|
|
|
|
if (client != NULL) {
|
|
entry = calloc(1, sizeof(struct tcp_client_entry));
|
|
|
|
entry->addr = strdup(addr);
|
|
entry->client = client;
|
|
TAILQ_INIT(&entry->handlers);
|
|
|
|
TAILQ_INSERT_TAIL(&tcp_clients, entry, entries);
|
|
|
|
if (poller == NULL) {
|
|
poller = SPDK_POLLER_REGISTER(remote_client_poll,
|
|
NULL, 4000);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int json_remote_client_send_command(const char *addr,
|
|
const char *command,
|
|
int32_t id,
|
|
struct spdk_jsonrpc_client_request *request,
|
|
json_remote_response_handler_fn fn,
|
|
void *arg) {
|
|
|
|
struct tcp_client_entry *entry = json_client_lookup(addr);
|
|
struct tcp_client_handler_entry *handler;
|
|
|
|
if (entry) {
|
|
handler = calloc(1, sizeof(struct tcp_client_handler_entry));
|
|
handler->command = strdup(command);
|
|
handler->id = id;
|
|
handler->fn = fn;
|
|
handler->arg = arg;
|
|
|
|
TAILQ_INSERT_TAIL(&entry->handlers, handler, entries);
|
|
spdk_jsonrpc_client_send_request(entry->client, request);
|
|
}
|
|
|
|
return 0;
|
|
}
|