/* Construct an empty dispatch_t. */ static void test_dispatch_empty(void *arg) { (void)arg; dispatch_t *d=NULL; dispatch_cfg_t *cfg=NULL; cfg = dcfg_new(); d = dispatch_new(cfg); tt_assert(d); done: dispatch_free(d); dcfg_free(cfg); }
static void test_dispatch_with_types(void *arg) { (void)arg; dispatch_t *d=NULL; dispatch_cfg_t *cfg=NULL; int r; cfg = dcfg_new(); r = dcfg_msg_set_type(cfg,5,3); r += dcfg_msg_set_chan(cfg,5,2); r += dcfg_add_recv(cfg,5,0,recv_typed_data); r += dcfg_type_set_fns(cfg,3,&coord_fns); tt_int_op(r, OP_EQ, 0); d = dispatch_new(cfg); tt_assert(d); dispatcher_in_use = d; /* Make this message get run immediately. */ r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL); tt_int_op(r, OP_EQ, 0); struct coord *xy = tor_malloc(sizeof(*xy)); xy->x = 13; xy->y = 37; msg_aux_data_t data = {.ptr = xy}; r = dispatch_send(d, 99/*sender*/, 2/*channel*/, 5/*msg*/, 3/*type*/, data); tt_int_op(r, OP_EQ, 0); tt_str_op(received_data, OP_EQ, "[13, 37]"); done: dispatch_free(d); dcfg_free(cfg); tor_free(received_data); dispatcher_in_use = NULL; }
/** * Starts a new dispatcher specialised in handling incoming data on * existing connections. */ dispatcher * dispatch_new_connection(router *r, char *allowed_chars) { char id = globalid++; return dispatch_new(id, CONNECTION, r, allowed_chars); }
/** * Starts a new dispatcher specialised in handling incoming connections * (and putting them on the queue for handling the connections). */ dispatcher * dispatch_new_listener(void) { char id = globalid++; return dispatch_new(id, LISTENER, NULL, NULL); }
/* Construct a dispatch_t with two messages, make sure that they both get * delivered. */ static void test_dispatch_simple(void *arg) { (void)arg; dispatch_t *d=NULL; dispatch_cfg_t *cfg=NULL; int r; cfg = dcfg_new(); r = dcfg_msg_set_type(cfg,0,0); r += dcfg_msg_set_chan(cfg,0,0); r += dcfg_add_recv(cfg,0,1,simple_recv1); r += dcfg_msg_set_type(cfg,1,0); r += dcfg_msg_set_chan(cfg,1,0); r += dcfg_add_recv(cfg,1,1,simple_recv2); r += dcfg_add_recv(cfg,1,1,simple_recv2); /* second copy */ tt_int_op(r, OP_EQ, 0); d = dispatch_new(cfg); tt_assert(d); dispatcher_in_use = d; msg_aux_data_t data = {.u64 = 7}; r = dispatch_send(d, 99, 0, 0, 0, data); tt_int_op(r, OP_EQ, 0); tt_int_op(total_recv1_simple, OP_EQ, 0); r = dispatch_flush(d, 0, INT_MAX); tt_int_op(r, OP_EQ, 0); tt_int_op(total_recv1_simple, OP_EQ, 7); tt_int_op(total_recv2_simple, OP_EQ, 0); total_recv1_simple = 0; r = dispatch_send(d, 99, 0, 1, 0, data); tt_int_op(r, OP_EQ, 0); r = dispatch_flush(d, 0, INT_MAX); tt_int_op(total_recv1_simple, OP_EQ, 0); tt_int_op(total_recv2_simple, OP_EQ, 140); tt_str_op(recv2_received, OP_EQ, "<>"); // no format function was set. done: dispatch_free(d); dcfg_free(cfg); tor_free(recv2_received); } /* Construct a dispatch_t with a message and no reciever; make sure that it * gets dropped properly. */ static void test_dispatch_no_recipient(void *arg) { (void)arg; dispatch_t *d=NULL; dispatch_cfg_t *cfg=NULL; int r; cfg = dcfg_new(); r = dcfg_msg_set_type(cfg,0,0); r += dcfg_msg_set_chan(cfg,0,0); tt_int_op(r, OP_EQ, 0); d = dispatch_new(cfg); tt_assert(d); dispatcher_in_use = d; msg_aux_data_t data = { .u64 = 7}; r = dispatch_send(d, 99, 0, 0, 0, data); tt_int_op(r, OP_EQ, 0); r = dispatch_flush(d, 0, INT_MAX); tt_int_op(r, OP_EQ, 0); done: dispatch_free(d); dcfg_free(cfg); } struct coord { int x; int y; }; static void free_coord(msg_aux_data_t d) { tor_free(d.ptr); }
int main(int argc, char *const argv[]) { int error = 0; log_debug("Parsing options"); Options *opts = parse_opt(argc, argv); if (!opts) { show_banner(); show_help(); return -1; } log_set_level(opts->loglevel); if (opts->logfile) { log_set_logfile(opts->logfile); log_set_logfile_level(LOG_LEVEL_MAX); } #ifdef HAVE_VSYSLOG if (opts->syslog) { log_set_syslog("daliserver"); } #endif if (opts->background) { daemonize(opts->pidfile); } else { show_banner(); } log_info("Starting daliserver"); log_debug("Initializing dispatch queue"); DispatchPtr dispatch = dispatch_new(); if (!dispatch) { error = -1; } else { //dispatch_set_timeout(dispatch, 100); UsbDaliPtr usb = NULL; if (!opts->dryrun) { log_debug("Initializing USB connection"); usb = usbdali_open(NULL, dispatch, opts->usbbus, opts->usbdev); if (!usb) { error = -1; } } if (opts->dryrun || usb) { log_debug("Initializing server"); ServerPtr server = server_open(dispatch, opts->address, opts->port, DEFAULT_NET_FRAMESIZE, net_frame_handler, usb); if (!server) { error = -1; } else { server_set_connection_destroy_callback(server, net_dequeue_connection, usb); if (usb) { usbdali_set_outband_callback(usb, dali_outband_handler, server); usbdali_set_inband_callback(usb, dali_inband_handler); } log_debug("Creating shutdown notifier"); killsocket = ipc_new(); if (!killsocket) { error = -1; } else { ipc_register(killsocket, dispatch); log_info("Server ready, waiting for events"); running = 1; signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); while (running && dispatch_run(dispatch, usbdali_get_timeout(usb))); log_info("Shutting daliserver down"); ipc_free(killsocket); } server_close(server); } if (usb) { usbdali_close(usb); } } dispatch_free(dispatch); } free_opt(opts); log_info("Exiting"); return error; }
push_callback_t * push_protobuf_message_new(const char *name, void *parent, push_parser_t *parser, push_protobuf_field_map_t *field_map) { void *context; push_callback_t *read_field_tag; push_callback_t *dispatch; push_callback_t *compose; push_callback_t *fold; /* * If the field map is NULL, return NULL ourselves. */ if (field_map == NULL) return NULL; /* * Create a memory context for the objects we're about to create. */ context = push_talloc_new(parent); if (context == NULL) return NULL; /* * Create the callbacks. */ if (name == NULL) name = "message"; read_field_tag = push_protobuf_varint32_new (push_talloc_asprintf(context, "%s.tag", name), context, parser); dispatch = dispatch_new (push_talloc_asprintf(context, "%s.dispatch", name), context, parser, field_map); compose = push_compose_new (push_talloc_asprintf(context, "%s.compose", name), context, parser, read_field_tag, dispatch); fold = push_fold_new (push_talloc_asprintf(context, "%s.fold", name), context, parser, compose); /* * Because of NULL propagation, we only have to check the last * result to see if everything was created okay. */ if (fold == NULL) goto error; return fold; error: /* * Before returning, free any objects we created before the error. */ push_talloc_free(context); return NULL; }
/** * Starts a new dispatcher specialised in handling incoming data on * existing connections. */ dispatcher * dispatch_new_connection(void) { char id = __sync_fetch_and_add(&globalid, 1); return dispatch_new(id, CONNECTION); }
/** * Starts a new dispatcher specialised in handling incoming connections * (and putting them on the queue for handling the connections). */ dispatcher * dispatch_new_listener(void) { char id = __sync_fetch_and_add(&globalid, 1); return dispatch_new(id, LISTENER); }