Steps toward node, factory and relay functionality.
This commit is contained in:
parent
17edf15cbd
commit
a3ebf4df37
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
TARGET = cmsg
|
TARGET = cmsg
|
||||||
OBJECTS = main.o harness.o net.o util.o relay.o hashtable.o dataq.o sexp.o sexpio.o
|
OBJECTS = main.o harness.o net.o util.o relay.o hashtable.o dataq.o sexp.o sexpio.o node.o
|
||||||
|
|
||||||
CFLAGS = -D_XOPEN_SOURCE=600 -Wall -O0 -g
|
CFLAGS = -D_XOPEN_SOURCE=600 -Wall -O0 -g
|
||||||
#CFLAGS = -D_XOPEN_SOURCE=600 -Wall -O3
|
#CFLAGS = -D_XOPEN_SOURCE=600 -Wall -O3
|
||||||
|
|
25
main.c
25
main.c
|
@ -13,11 +13,36 @@ typedef unsigned char u_char;
|
||||||
#include "cmsg_private.h"
|
#include "cmsg_private.h"
|
||||||
#include "harness.h"
|
#include "harness.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "ref.h"
|
||||||
|
#include "sexp.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
static node_t *factory_construct(node_class_t *nc, sexp_t *args) {
|
||||||
|
return malloc(sizeof(node_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void factory_handle_message(node_t *n, sexp_t *m) {
|
||||||
|
info("factory_handle_message\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static node_class_t factory_class = {
|
||||||
|
.name = "factory",
|
||||||
|
.construct = factory_construct,
|
||||||
|
.destroy = (node_destructor_fn_t) free,
|
||||||
|
.handle_message = factory_handle_message
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_factory(void) {
|
||||||
|
bind_node(cmsg_cstring_bytes("factory"), new_node(&factory_class, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
info("cmsg, Copyright (C) 2010 Tony Garnock-Jones. All rights reserved.\n");
|
info("cmsg, Copyright (C) 2010 Tony Garnock-Jones. All rights reserved.\n");
|
||||||
event_init();
|
event_init();
|
||||||
info("Using libevent version %s\n", event_get_version());
|
info("Using libevent version %s\n", event_get_version());
|
||||||
|
init_node();
|
||||||
|
init_factory();
|
||||||
start_net(5671);
|
start_net(5671);
|
||||||
boot_harness();
|
boot_harness();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "cmsg_private.h"
|
||||||
|
#include "ref.h"
|
||||||
|
#include "sexp.h"
|
||||||
|
#include "hashtable.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
static hashtable_t node_class_table;
|
||||||
|
static hashtable_t directory;
|
||||||
|
|
||||||
|
static void *node_incref(void *arg) {
|
||||||
|
return INCREF((node_t *) arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void node_decref(void *arg) {
|
||||||
|
DECREF((node_t *) arg, node_destructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_node(void) {
|
||||||
|
init_hashtable(&node_class_table,
|
||||||
|
31,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
init_hashtable(&directory,
|
||||||
|
10007,
|
||||||
|
node_incref,
|
||||||
|
node_decref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_node_class(node_class_t *nc) {
|
||||||
|
cmsg_bytes_t key = cmsg_cstring_bytes(nc->name);
|
||||||
|
if (hashtable_contains(&node_class_table, key)) {
|
||||||
|
die("Duplicate node class name %s\n", nc->name);
|
||||||
|
}
|
||||||
|
hashtable_put(&node_class_table, key, nc);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_class_t *lookup_node_class(cmsg_bytes_t name) {
|
||||||
|
node_class_t *nc = NULL;
|
||||||
|
hashtable_get(&node_class_table, name, (void **) &nc);
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_t *new_node(node_class_t *nc, sexp_t *args) {
|
||||||
|
node_t *n = nc->construct(nc, args);
|
||||||
|
n->refcount = ZERO_REFCOUNT();
|
||||||
|
n->node_class = nc;
|
||||||
|
init_hashtable(&n->names, 5, NULL, NULL);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unbind_on_destroy(void *context, cmsg_bytes_t key, void *value) {
|
||||||
|
unbind_node(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void node_destructor(node_t *n) {
|
||||||
|
hashtable_foreach(&n->names, unbind_on_destroy, NULL);
|
||||||
|
destroy_hashtable(&n->names);
|
||||||
|
n->node_class->destroy(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_t *lookup_node(cmsg_bytes_t name) {
|
||||||
|
node_t *n = NULL;
|
||||||
|
hashtable_get(&directory, name, (void **) &n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bind_node(cmsg_bytes_t name, node_t *n) {
|
||||||
|
if (hashtable_contains(&directory, name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hashtable_put(&directory, name, n);
|
||||||
|
hashtable_put(&n->names, name, NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unbind_node(cmsg_bytes_t name) {
|
||||||
|
node_t *n = NULL;
|
||||||
|
hashtable_get(&directory, name, (void **) &n);
|
||||||
|
if (n == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
hashtable_erase(&n->names, name);
|
||||||
|
hashtable_erase(&directory, name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int post_node(cmsg_bytes_t node, cmsg_bytes_t name, sexp_t *body) {
|
||||||
|
static sexp_t *post_atom = NULL;
|
||||||
|
sexp_t *msg = NULL;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (post_atom == NULL) {
|
||||||
|
post_atom = INCREF(sexp_bytes(cmsg_cstring_bytes("post")));
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = sexp_cons(body, msg);
|
||||||
|
msg = sexp_cons(sexp_bytes(name), msg);
|
||||||
|
msg = sexp_cons(post_atom, msg);
|
||||||
|
INCREF(msg);
|
||||||
|
result = send_node(node, msg);
|
||||||
|
DECREF(msg, sexp_destructor);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_node(cmsg_bytes_t node, sexp_t *message) {
|
||||||
|
node_t *n = lookup_node(node);
|
||||||
|
if (n == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n->node_class->handle_message(n, message);
|
||||||
|
return 1;
|
||||||
|
}
|
30
node.h
30
node.h
|
@ -2,15 +2,37 @@
|
||||||
#define cmsg_node_h
|
#define cmsg_node_h
|
||||||
|
|
||||||
typedef struct node_t_ {
|
typedef struct node_t_ {
|
||||||
|
refcount_t refcount;
|
||||||
struct node_class_t_ *node_class;
|
struct node_class_t_ *node_class;
|
||||||
cmsg_bytes_t name; /* used as (partial) routing key for metamessages */
|
hashtable_t names;
|
||||||
} node_t;
|
} node_t;
|
||||||
|
|
||||||
|
typedef node_t *(*node_constructor_fn_t)(struct node_class_t_ *nc, sexp_t *args);
|
||||||
|
typedef void (*node_destructor_fn_t)(node_t *n);
|
||||||
|
typedef void (*node_message_handler_fn_t)(node_t *n, sexp_t *m);
|
||||||
|
|
||||||
typedef struct node_class_t_ {
|
typedef struct node_class_t_ {
|
||||||
void (*destroy)(node_t *n);
|
char const *name;
|
||||||
void (*handle_message)(node_t *n, msg_t *m);
|
node_constructor_fn_t construct;
|
||||||
|
node_destructor_fn_t destroy;
|
||||||
|
node_message_handler_fn_t handle_message;
|
||||||
} node_class_t;
|
} node_class_t;
|
||||||
|
|
||||||
extern node_t *new_node(
|
extern void init_node(void);
|
||||||
|
|
||||||
|
extern void basic_node_destroy(node_t *n);
|
||||||
|
|
||||||
|
extern void register_node_class(node_class_t *nc);
|
||||||
|
extern node_class_t *lookup_node_class(cmsg_bytes_t name);
|
||||||
|
|
||||||
|
extern node_t *new_node(node_class_t *nc, sexp_t *args);
|
||||||
|
extern void node_destructor(node_t *n);
|
||||||
|
|
||||||
|
extern node_t *lookup_node(cmsg_bytes_t name);
|
||||||
|
extern int bind_node(cmsg_bytes_t name, node_t *n);
|
||||||
|
extern int unbind_node(cmsg_bytes_t name);
|
||||||
|
|
||||||
|
extern int post_node(cmsg_bytes_t node, cmsg_bytes_t name, sexp_t *body);
|
||||||
|
extern int send_node(cmsg_bytes_t node, sexp_t *message);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
87
relay.c
87
relay.c
|
@ -3,6 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
@ -31,9 +32,23 @@ struct boot_args {
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void send_sexp_syntax_error(IOHandle *h, char const *message) {
|
||||||
|
sexp_t *m = NULL;
|
||||||
|
m = sexp_cons(sexp_bytes(cmsg_cstring_bytes("http://people.csail.mit.edu/rivest/Sexp.txt")), m);
|
||||||
|
m = sexp_cons(sexp_bytes(cmsg_cstring_bytes(message)), m);
|
||||||
|
m = sexp_cons(sexp_bytes(cmsg_cstring_bytes("error")), m);
|
||||||
|
INCREF(m);
|
||||||
|
|
||||||
|
iohandle_clear_error(h);
|
||||||
|
ICHECK(sexp_write(h, m), "send_sexp_syntax_error sexp_write");
|
||||||
|
DECREF(m, sexp_destructor);
|
||||||
|
iohandle_flush(h); /* ignore result here, there's not much we can do with it */
|
||||||
|
}
|
||||||
|
|
||||||
static void relay_main(struct boot_args *args) {
|
static void relay_main(struct boot_args *args) {
|
||||||
IOHandle *h = new_iohandle(args->fd);
|
IOHandle *h = new_iohandle(args->fd);
|
||||||
IOHandle *out = new_iohandle(1);
|
IOHandle *out_handle = new_iohandle(1);
|
||||||
|
sexp_t *message = NULL; /* held */
|
||||||
|
|
||||||
{
|
{
|
||||||
char name[256];
|
char name[256];
|
||||||
|
@ -43,41 +58,57 @@ static void relay_main(struct boot_args *args) {
|
||||||
|
|
||||||
free(args);
|
free(args);
|
||||||
|
|
||||||
iohandle_write(h, cmsg_cstring_bytes("Hi\n"));
|
iohandle_write(h, cmsg_cstring_bytes("(3:hop1:0)"));
|
||||||
ICHECK(iohandle_flush(h), "iohandle_flush 1");
|
ICHECK(iohandle_flush(h), "iohandle_flush 1");
|
||||||
nap(1000);
|
|
||||||
iohandle_write(h, cmsg_cstring_bytes("Proceed\n"));
|
|
||||||
//iohandle_settimeout(h, 3, 0);
|
//iohandle_settimeout(h, 3, 0);
|
||||||
|
|
||||||
loop:
|
while (1) {
|
||||||
{
|
DECREF(message, sexp_destructor);
|
||||||
sexp_t *x = sexp_read(h);
|
message = NULL;
|
||||||
switch (h->error_kind) {
|
message = INCREF(sexp_read(h));
|
||||||
case 0:
|
|
||||||
fflush(NULL);
|
|
||||||
sexp_write(out, x);
|
|
||||||
iohandle_write(out, cmsg_cstring_bytes("\n"));
|
|
||||||
ICHECK(iohandle_flush(out), "iohandle_flush out");
|
|
||||||
DECREF(x, sexp_destructor);
|
|
||||||
iohandle_write(h, cmsg_cstring_bytes("OK, proceed\n"));
|
|
||||||
goto loop;
|
|
||||||
|
|
||||||
case EVBUFFER_TIMEOUT:
|
if (h->error_kind != 0) goto handle_error;
|
||||||
info("Timeout\n");
|
|
||||||
iohandle_clear_error(h);
|
|
||||||
iohandle_write(h, cmsg_cstring_bytes("Timed out\n"));
|
|
||||||
ICHECK(iohandle_flush(h), "iohandle_flush 2");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
fflush(NULL);
|
||||||
info("Error! 0x%04X\n", h->error_kind);
|
sexp_write(out_handle, message);
|
||||||
break;
|
iohandle_write(out_handle, cmsg_cstring_bytes("\n"));
|
||||||
}
|
ICHECK(iohandle_flush(out_handle), "iohandle_flush out_handle");
|
||||||
|
|
||||||
|
iohandle_write(h, cmsg_cstring_bytes("OK, proceed\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ICHECK(close(h->fd), "close");
|
handle_error:
|
||||||
|
switch (h->error_kind) {
|
||||||
|
case EVBUFFER_EOF:
|
||||||
|
info("Disconnecting fd %d normally.\n", h->fd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEXP_ERROR_OVERFLOW:
|
||||||
|
send_sexp_syntax_error(h, "sexp too big");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEXP_ERROR_SYNTAX:
|
||||||
|
send_sexp_syntax_error(h, "sexp syntax error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
warn("Relay handle error on fd %d: 0x%04X\n", h->fd, h->error_kind);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
goto closedown;
|
||||||
|
|
||||||
|
closedown:
|
||||||
|
if (close(h->fd) == -1) {
|
||||||
|
/* log errors as warnings here and keep on trucking */
|
||||||
|
warn("Closing file descriptor %d produced errno %d: %s\n",
|
||||||
|
h->fd, errno, strerror(errno));
|
||||||
|
}
|
||||||
delete_iohandle(h);
|
delete_iohandle(h);
|
||||||
delete_iohandle(out);
|
delete_iohandle(out_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_relay(struct sockaddr_in const *peername, int fd) {
|
void start_relay(struct sockaddr_in const *peername, int fd) {
|
||||||
|
|
Loading…
Reference in New Issue