int maltcp_ctx_poller_del_endpoint( void *self, mal_poller_t *mal_poller, mal_endpoint_t *mal_endpoint) { maltcp_poller_data_t *poller_data = (maltcp_poller_data_t *) mal_poller_get_poller_data(mal_poller); maltcp_endpoint_data_t *endpoint_data = (maltcp_endpoint_data_t *) mal_endpoint_get_endpoint_data(mal_endpoint); int rc = 0; clog_debug(maltcp_logger, "maltcp_ctx_poller_del_endpoint(): %s\n", mal_endpoint_get_uri(mal_endpoint)); if (poller_data->poller == NULL) { clog_error(maltcp_logger, ""); return -1; } rc = zpoller_remove(poller_data->poller, endpoint_data->socket); if (rc != 0) { clog_error(maltcp_logger, "maltcp_ctx_poller_del_endpoint(): zpoller null\n"); return rc; } rc = maltcp_del_endpoint(poller_data, mal_endpoint); clog_debug(maltcp_logger, "maltcp_ctx_poller_del_endpoint: return %d\n",rc); return rc; }
int maltcp_ctx_server_socket_create(int port, int backlog) { clog_debug(maltcp_logger, "maltcp_ctx: creates TCP server socket.\n"); int listen_socket = socket(AF_INET, SOCK_STREAM, 0); if (listen_socket == -1) { clog_error(maltcp_logger, "Failed to create listen socket: %s", strerror(errno)); return -1; } int one = 1; setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); // setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one)); // setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); struct sockaddr_in server_addr; bzero((char *) &server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port); if (bind(listen_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) { clog_error(maltcp_logger, "Failed to bind server to port %d: %s\n", port, strerror(errno)); return -1; } if (listen(listen_socket, backlog) == -1) { clog_error(maltcp_logger, "Failed to listen: %s", strerror(errno)); return -1; } clog_debug(maltcp_logger, "maltcp_ctx: TCP server socket created.\n"); return listen_socket; }
// internal functions, should not be visible from outside this module int malzmq_encode_string( mal_string_t *to_encode, malzmq_mapping_directory_t *mapping_directory, mal_encoder_t *encoder, void *cursor) { bool mdk_encode = false; unsigned int md_key; // find the string in the mapping directory if (mapping_directory != NULL) { int rc = mapping_directory->get_key_fn(to_encode, &md_key); if ((rc == 0) && (md_key > 0)) mdk_encode = true; } if (mdk_encode) { int opt_mdk = (-md_key); // check opt_mdk is negative if (! (opt_mdk < 0)) { clog_error(malzmq_logger, "malzmq_encode_string, bad optional key: %d.", opt_mdk); return -1; } malbinary_encoder_encode_integer(encoder, cursor, opt_mdk); } else { // check length is not too large int len = strlen(to_encode); if (! (len >= 0)) { clog_error(malzmq_logger, "malzmq_encode_string, length too large: %d.", len); return -1; } malbinary_encoder_encode_integer(encoder, cursor, len); malbinary_write_array(to_encode, len, cursor); } return 0; }
/* Sets up the signal handler for SIGWINCH * Returns -1 on error. Or 0 on success */ static int set_up_signal(void) { struct sigaction action; action.sa_handler = signal_handler; sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGWINCH, &action, NULL) < 0) { clog_error(CLOG_CGDB, "sigaction failed "); return -1; } if (sigaction(SIGINT, &action, NULL) < 0) { clog_error(CLOG_CGDB, "sigaction failed "); return -1; } if (sigaction(SIGTERM, &action, NULL) < 0) { clog_error(CLOG_CGDB, "sigaction failed "); return -1; } if (sigaction(SIGQUIT, &action, NULL) < 0) { clog_error(CLOG_CGDB, "sigaction failed "); return -1; } if (sigaction(SIGCHLD, &action, NULL) < 0) { clog_error(CLOG_CGDB, "sigaction failed "); return -1; } return 0; }
void maltcp_ctx_socket_destroy(maltcp_ctx_connection_t *cnx_ptr) { if (close(cnx_ptr->socket) != 0) { clog_error(maltcp_logger, "maltcp_ctx_socket_destroy: Failed to close socket.\n"); } if (pthread_mutex_destroy(&cnx_ptr->lock) != 0) { clog_error(maltcp_logger, "maltcp_ctx_socket_destroy: Failed to destroy mutex.\n"); } }
maltcp_ctx_connection_t *maltcp_ctx_socket_connect(maltcp_ctx_t *self, mal_uri_t *socket_uri) { maltcp_ctx_connection_t *cnx_ptr = (maltcp_ctx_connection_t *) zhash_lookup(self->cnx_table, socket_uri); if (cnx_ptr == NULL) { clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: open a new PTP socket\n"); // Create a new connection struct hostent *server; int client_socket = socket(AF_INET, SOCK_STREAM, 0); if (client_socket == -1) { clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to create client socket: %s\n", strerror(errno)); return NULL; } char *ipaddr = maltcp_get_host_from_uri(socket_uri); int port = maltcp_get_port_from_uri(socket_uri); clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: %s %d\n", ipaddr, port); if ((server = gethostbyname(ipaddr)) == NULL) { clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to to get address: %s\n", strerror(errno)); free(ipaddr); return NULL; } free(ipaddr); struct sockaddr_in server_addr; bzero((char *) &server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&server_addr.sin_addr.s_addr, server->h_length); server_addr.sin_port = htons(port); if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { clog_error(maltcp_logger, "maltcp_ctx_socket_connect: failed to connect: %s\n", strerror(errno)); return NULL; } clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: connected to %s\n", socket_uri); clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: update TCP connections table\n"); cnx_ptr = maltcp_ctx_connection_register_outgoing(self, client_socket, socket_uri); // Register a zloop poller for this connection. zmq_pollitem_t poller = { NULL, client_socket, ZMQ_POLLIN }; int rc = zloop_poller(self->zloop, &poller, maltcp_ctx_socket_receive, self); assert(rc == 0); } else { clog_debug(maltcp_logger, "maltcp_ctx_socket_connect: use existing connection (%d) for %s\n", cnx_ptr->socket, socket_uri); } return cnx_ptr; }
int tgdb_process(struct tgdb * tgdb) { const int n = 4096; static char buf[n]; ssize_t size; int result = 0; // Cleanup those zombies! tgdb_handle_sigchld(tgdb); // If ^c has been typed at the prompt, clear the queues tgdb_handle_control_c(tgdb); size = io_read(tgdb->debugger_stdout, buf, n); if (size < 0) { // Error reading from GDB clog_error(CLOG_CGDB, "Error reading from gdb's stdout, closing down"); result = -1; tgdb_add_quit_command(tgdb); } else if (size == 0) { // Read EOF from GDB clog_info(CLOG_GDBIO, "read EOF from GDB, closing down"); tgdb_add_quit_command(tgdb); } else { // Read some GDB console output, process it result = annotations_parser_io(tgdb->parser, buf, size); } return result; }
int main(int argc, char *argv[]) { int level = CLOG_DEFAULT; const char *lname = "DEFAULT"; clog_init(stdout, level, CLOG_DEFAULT_TS_FMT); if(argc == 2) { if(!strcmp("FATAL", argv[1])) { clog_set_level(level = CLOG_FATAL); lname = "FATAL"; } if(!strcmp("ERROR", argv[1])) { clog_set_level(level = CLOG_ERROR); lname = "ERROR"; } if(!strcmp("WARN", argv[1])) { clog_set_level(level = CLOG_WARN); lname = "WARN"; } if(!strcmp("INFO", argv[1])) { clog_set_level(level = CLOG_INFO); lname = "INFO"; } if(!strcmp("DEBUG", argv[1])) { clog_set_level(level = CLOG_DEBUG); lname = "DEBUG"; } if(!strcmp("TRACE", argv[1])) { clog_set_level(level = CLOG_TRACE); lname = "TRACE"; } } fprintf(stdout, "--- %s ---\n", lname); clog_fatal("this is %s log", "fatal"); clog_error("this is %s log", "error"); clog_warn("this is %s log", "warn"); clog_info("this is %s log", "info"); clog_debug("this is %s log", "debug"); clog_trace("this is %s log", "trace"); return 0; }
int maltcp_ctx_poller_wait( void *self, mal_poller_t *mal_poller, mal_endpoint_t **mal_endpoint, int timeout) { maltcp_poller_data_t *poller_data = (maltcp_poller_data_t *) mal_poller_get_poller_data(mal_poller); int rc = 0; clog_debug(maltcp_logger, "maltcp_ctx_poller_wait(%d)\n", timeout); zsock_t *which = (zsock_t *) zpoller_wait(poller_data->poller, timeout); if (zpoller_terminated(poller_data->poller)) { clog_debug(maltcp_logger, "maltcp_ctx_poller_wait: zpoller_terminated.\n"); return -1; } if (which) { maltcp_endpoint_data_t *endpoint_data = maltcp_get_endpoint(poller_data, which); if (endpoint_data != NULL) { *mal_endpoint = endpoint_data->mal_endpoint; clog_debug(maltcp_logger, "maltcp_ctx_poller_wait: data available for end-point %s\n", mal_endpoint_get_uri(*mal_endpoint)); } else { clog_error(maltcp_logger, "maltcp_ctx_poller_wait: cannot find corresponding end-point\n"); return -1; } } else { *mal_endpoint = NULL; } return rc; }
/* See interface.h for function descriptions. */ int if_init(void) { if (init_curses()) { clog_error(CLOG_CGDB, "Unable to initialize the ncurses library"); return -1; } hl_groups_instance = hl_groups_initialize(); if (!hl_groups_instance) { clog_error(CLOG_CGDB, "Unable to setup highlighting groups"); return -1; } if (hl_groups_setup(hl_groups_instance) == -1) { clog_error(CLOG_CGDB, "Unable to setup highlighting groups"); return -1; } /* Set up the signal handler to catch SIGWINCH */ if (set_up_signal() == -1) { clog_error(CLOG_CGDB, "Unable to handle signal: SIGWINCH"); return -1; } if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1) { screen_size.ws_row = swin_lines(); screen_size.ws_col = swin_cols(); } /* Create the file dialog object */ fd = filedlg_new(0, 0, HEIGHT, WIDTH); /* Set up window layout */ window_shift = (int) ((HEIGHT / 2) * (cur_win_split / 2.0)); switch (if_layout()) { case 2: return 4; } G_line_number = ibuf_init(); return 0; }
/* These functions are used to communicate with the inferior */ int tgdb_send_inferior_char(struct tgdb *tgdb, char c) { if (io_write_byte(tgdb->inferior_stdout, c) == -1) { clog_error(CLOG_CGDB, "io_write_byte failed"); return -1; } return 0; }
maltcp_ctx_connection_t *maltcp_ctx_connection_create(int socket) { maltcp_ctx_connection_t *cnx_ptr = (maltcp_ctx_connection_t*) malloc(sizeof(maltcp_ctx_connection_t)); // Initialize the mutex if (pthread_mutex_init(&cnx_ptr->lock, NULL) != 0) { clog_error(maltcp_logger, "maltcp_ctx_connection_create: failed to initialize mutex."); free(cnx_ptr); return NULL; } cnx_ptr->socket = socket; return cnx_ptr; }
/* * Gets the users home dir and creates the config directory. * * Also returns the logs directory. * * @param tgdb * The tgdb context. * * @param logs_dir * Should be FSUTIL_PATH_MAX in size on way in. * On way out, it will be the path to the logs dir * * \return * -1 on error, or 0 on success */ static int tgdb_initialize_config_dir(struct tgdb *tgdb, char *logs_dir) { char config_dir[FSUTIL_PATH_MAX]; char *home_dir = getenv("HOME"); /* Make sure the toplevel .cgdb dir exists */ snprintf(config_dir, FSUTIL_PATH_MAX, "%s/.cgdb", home_dir); if (!fs_util_create_dir(config_dir)) { clog_error(CLOG_CGDB, "Could not create dir %s", config_dir); return -1; } /* Try to create full .cgdb/logs directory */ snprintf(logs_dir, FSUTIL_PATH_MAX, "%s/.cgdb/logs", home_dir); if (!fs_util_create_dir(logs_dir)) { clog_error(CLOG_CGDB, "Could not create dir %s", logs_dir); return -1; } return 0; }
ssize_t tgdb_recv_inferior_data(struct tgdb * tgdb, char *buf, size_t n) { ssize_t size; /* read all the data possible from the child that is ready. */ size = io_read(tgdb->inferior_stdin, buf, n); if (size < 0) { clog_error(CLOG_CGDB, "inferior_fd read failed"); return -1; } return size; }
int maltcp_add_endpoint(maltcp_poller_data_t *poller_data, mal_endpoint_t *endpoint) { clog_info(maltcp_logger, " *** maltcp_add_endpoint: %s\n", mal_endpoint_get_uri(endpoint)); if (poller_data->idx < poller_data->max) { // Includes the structure in the table poller_data->endpoints[poller_data->idx++] = (maltcp_endpoint_data_t *) mal_endpoint_get_endpoint_data(endpoint); return 0; } else { clog_error(maltcp_logger, "Error :: Cannot add more than %d endpoints\n", poller_data->max); return -1; } }
int maltcp_ctx_socket_send(maltcp_ctx_connection_t *cnx, malbinary_cursor_t *cursor) { // Lock TCP connection. pthread_mutex_lock(&cnx->lock); clog_debug(maltcp_logger, "maltcp_ctx_socket_send: send TCP message, size=%d\n", malbinary_cursor_get_length(cursor)); int rc = send(cnx->socket, cursor->body_ptr, malbinary_cursor_get_length(cursor), 0); if (rc < 0) clog_error(maltcp_logger, "maltcp_ctx_socket_send: error sending message.\n"); else clog_debug(maltcp_logger, "maltcp_ctx_socket_send: message sent.\n"); // Unock TCP connection. pthread_mutex_unlock(&cnx->lock); return rc; }
// This function is called when an incoming connection is detected on the // listening socket. It accepts the connection and registers the appropriate // poller to receive message. int maltcp_ctx_socket_accept(zloop_t *zloop, zmq_pollitem_t *poller, void *arg) { maltcp_ctx_t *self = (maltcp_ctx_t *) arg; clog_debug(maltcp_logger, "maltcp_ctx: TCP server socket accept.\n"); if (self->mal_socket == -1) { // The context is closed, return clog_debug(maltcp_logger, "maltcp_ctx_socket_accept: socket (%d) closed\n", poller->fd); return -1; } // Accept incoming connection and register it. struct sockaddr src_addr; int new_socket = -1; socklen_t len = sizeof(struct sockaddr_in); // Note: May be we could use poller->fd to replace self->mal_socket if ((new_socket = accept(self->mal_socket, &src_addr, &len)) == -1) { clog_error(maltcp_logger, "Failed to accept: %s\n", strerror(errno)); return -1; } if (clog_is_loggable(maltcp_logger, CLOG_DEBUG_LEVEL)) { // Needed only for debug. char src_ipstr[INET6_ADDRSTRLEN]; int src_port; if (src_addr.sa_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *)&src_addr; src_port = ntohs(s->sin_port); inet_ntop(AF_INET, &s->sin_addr, src_ipstr, sizeof src_ipstr); } else { // AF_INET6 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&src_addr; src_port = ntohs(s->sin6_port); inet_ntop(AF_INET6, &s->sin6_addr, src_ipstr, sizeof src_ipstr); } clog_debug(maltcp_logger, "maltcp_ctx_socket_accept: Source URI: %s%s:%d\n", MALTCP_URI, src_ipstr, src_port); } zmq_pollitem_t poller2 = { NULL, new_socket, ZMQ_POLLIN }; int rc = zloop_poller(zloop, &poller2, maltcp_ctx_socket_receive, self); assert(rc == 0); // Note: do not register the connection since the uri is not yet precisely known. clog_debug(maltcp_logger, "maltcp_ctx: TCP connection established.\n"); return 0; }
void *maltcp_ctx_create_endpoint(void *maltcp_ctx, mal_endpoint_t *mal_endpoint) { maltcp_ctx_t *self = (maltcp_ctx_t *) maltcp_ctx; maltcp_endpoint_data_t *endpoint_data = NULL; clog_debug(maltcp_logger, "maltcp_ctx_create_endpoint()\n"); if (mal_endpoint) { endpoint_data = (maltcp_endpoint_data_t *) zmalloc(sizeof(maltcp_endpoint_data_t)); assert(endpoint_data); // Initialize the endpoint ZMQ specific state endpoint_data->maltcp_ctx = self; endpoint_data->mal_endpoint = mal_endpoint; mal_endpoint_set_endpoint_data(mal_endpoint, endpoint_data); clog_debug(maltcp_logger, "maltcp_ctx_create_endpoint: initialize endpoint\n"); // Initialize the endpoint mal_uri_t *handler_uri = maltcp_get_service_from_uri(mal_endpoint_get_uri(endpoint_data->mal_endpoint)); clog_debug(maltcp_logger, "maltcp_ctx_create_endpoint: initialize endpoint -> %s\n", handler_uri); // Create a socket connected to the zloop to receive // MAL messages to be handled by this actor void *zloop_socket = zsocket_new(self->zmq_ctx, ZMQ_DEALER); // Keep the socket endpoint_data->socket = zloop_socket; // The identity of the handler is its URI zmq_setsockopt(zloop_socket, ZMQ_IDENTITY, handler_uri, strlen(handler_uri)); // Connect to the zloop clog_debug(maltcp_logger, "maltcp_ctx_create_endpoint: connect to the zloop\n"); zmq_connect(zloop_socket, ZLOOP_ENDPOINTS_SOCKET_URI); clog_debug(maltcp_logger, "maltcp_ctx_create_endpoint: initialized.\n"); } else { clog_error(maltcp_logger, "maltcp_ctx_create_endpoint, cannot create end-point: %s\n", mal_endpoint_get_uri(endpoint_data->mal_endpoint)); } return endpoint_data; }
static void if_print_internal(const char *buf, enum ScrInputKind kind) { if (!gdb_scroller) { clog_error(CLOG_CGDB, "%s", buf); return; } /* Print it to the scroller */ scr_add(gdb_scroller, buf, kind); if (get_gdb_height() > 0) { scr_refresh(gdb_scroller, focus == GDB, WIN_NO_REFRESH); /* Make sure cursor reappears in source window if focus is there */ if (focus == CGDB) swin_wnoutrefresh(src_viewer->win); swin_doupdate(); } }
/* init_curses: Initializes curses and sets up the terminal properly. * ------------ * * Return Value: Zero on success, non-zero on failure. */ static int init_curses() { char escdelay[] = "ESCDELAY=0"; if (putenv(escdelay)) { clog_error(CLOG_CGDB, "putenv(\"%s\") failed", escdelay); } swin_initscr(); /* Start curses mode */ if (swin_has_colors()) { swin_start_color(); swin_use_default_colors(); } swin_refresh(); /* Refresh the initial window once */ curses_initialized = 1; return 0; }
/** * Called to process the sigchld signal, and clean up zombies! * * @param tgdb * The tgdb instance * * @return * 0 on success or -1 on error */ static int tgdb_handle_sigchld(struct tgdb *tgdb) { int result = 0; int status; if (tgdb->has_sigchld_recv) { int waitpid_result; do { waitpid_result = waitpid(tgdb->debugger_pid, &status, WNOHANG); if (waitpid_result == -1) { result = -1; clog_error(CLOG_CGDB, "waitpid error"); break; } } while (waitpid_result != 0); tgdb->has_sigchld_recv = 0; } return result; }
static int tgdb_open_new_tty(struct tgdb *tgdb, int *inferior_stdin, int *inferior_stdout) { if (tgdb->pty_pair) pty_pair_destroy(tgdb->pty_pair); tgdb->pty_pair = pty_pair_create(); if (!tgdb->pty_pair) { clog_error(CLOG_CGDB, "pty_pair_create failed"); return -1; } *inferior_stdin = pty_pair_get_masterfd(tgdb->pty_pair); *inferior_stdout = pty_pair_get_masterfd(tgdb->pty_pair); tgdb_request_ptr request_ptr; request_ptr = (tgdb_request_ptr)cgdb_malloc(sizeof (struct tgdb_request)); request_ptr->header = TGDB_REQUEST_TTY; request_ptr->choice.tty_command.slavename = pty_pair_get_slavename(tgdb->pty_pair); tgdb_run_or_queue_request(tgdb, request_ptr, true); return 0; }
maltcp_ctx_t *maltcp_ctx_new(mal_ctx_t *mal_ctx, char *hostname, char *port, maltcp_header_t *maltcp_header, // TODO: no longer used bool verbose) { maltcp_ctx_t *self = (maltcp_ctx_t *) malloc(sizeof(maltcp_ctx_t)); if (!self) return NULL; self->mal_ctx = mal_ctx; self->hostname = hostname; self->port = port; self->maltcp_header = maltcp_header; self->encoder = malbinary_encoder_new(true); self->decoder = malbinary_decoder_new(true); self->root_uri = (char *) malloc(strlen(hostname) + strlen(port) + 10 + 1); sprintf((char*) self->root_uri, "%s%s:%s", MALTCP_URI, hostname, port); clog_debug(maltcp_logger, "maltcp_ctx_new: root_uri=%s\n", self->root_uri); zctx_t *zmq_ctx = zctx_new(); self->zmq_ctx = zmq_ctx; self->cnx_table = zhash_new(); // Creates the TCP listening socket int listen = maltcp_ctx_server_socket_create(atoi(port), BACKLOG); //assert(listen >= 0); if (listen < 0) { clog_error(maltcp_logger, "EXCEPTION:: maltcp_ctx_new: listen = %d\n", listen); return NULL; } self->mal_socket = listen; clog_debug(maltcp_logger, "maltcp_ctx: ptp listening to: %s\n", port); //inproc void *endpoints_socket = zsocket_new(zmq_ctx, ZMQ_ROUTER); self->endpoints_socket = endpoints_socket; zsocket_bind(endpoints_socket, ZLOOP_ENDPOINTS_SOCKET_URI); zloop_t *zloop = zloop_new(); // TODO (AF): It seems that adding poller from outside of handler is not correctly // supported by ZMQ. We should provide an inproc socket allowing to add the needed // poller. However it seems that a timer regularly awaking the zloop corrects this // issue. zloop_timer(zloop, 100, 0, zloop_timer_handle, self); // zloop_set_verbose(zloop, true); self->zloop = zloop; zmq_pollitem_t poller = { NULL, listen, ZMQ_POLLIN }; int rc = zloop_poller(zloop, &poller, maltcp_ctx_socket_accept, self); assert(rc == 0); mal_ctx_set_binding( mal_ctx, self, maltcp_ctx_create_uri, maltcp_ctx_create_endpoint, maltcp_ctx_destroy_endpoint, maltcp_ctx_create_poller, maltcp_ctx_destroy_poller, maltcp_ctx_poller_add_endpoint, maltcp_ctx_poller_del_endpoint, maltcp_ctx_send_message, maltcp_ctx_recv_message, maltcp_ctx_poller_wait, maltcp_ctx_destroy_message, maltcp_ctx_start, maltcp_ctx_stop, maltcp_ctx_destroy); return self; }
static int highlight_node(struct list_node *node) { int i; int ret; int line = 0; int length = 0; int lasttype = -1; struct token_data tok_data; struct tokenizer *t = tokenizer_init(); struct buffer *buf = &node->file_buf; for (i = 0; i < sbcount(buf->lines); i++) { sbfree(buf->lines[i].attrs); buf->lines[i].attrs = NULL; } if (!buf->file_data) { for (line = 0; line < sbcount(buf->lines); line++) { struct source_line *sline = &buf->lines[line]; tokenizer_set_buffer(t, sline->line, buf->language); length = 0; lasttype = -1; while ((ret = tokenizer_get_token(t, &tok_data)) > 0) { if (tok_data.e == TOKENIZER_NEWLINE) break; enum hl_group_kind hlg = hlg_from_tokenizer_type(tok_data.e, tok_data.data); /* Add attribute if highlight group has changed */ if (lasttype != hlg) { sbpush(buf->lines[line].attrs, hl_line_attr(length, hlg)); lasttype = hlg; } /* Add the text and bump our length */ length += strlen(tok_data.data); } } } else { if (tokenizer_set_buffer(t, buf->file_data, buf->language) == -1) { if_print_message("%s:%d tokenizer_set_buffer error", __FILE__, __LINE__); return -1; } while ((ret = tokenizer_get_token(t, &tok_data)) > 0) { if (tok_data.e == TOKENIZER_NEWLINE) { if (length > buf->max_width) buf->max_width = length; length = 0; lasttype = -1; line++; } else { enum hl_group_kind hlg = hlg_from_tokenizer_type(tok_data.e, tok_data.data); if (hlg == HLG_LAST) { clog_error(CLOG_CGDB, "Bad hlg_type for '%s', e==%d\n", tok_data.data, tok_data.e); hlg = HLG_TEXT; } /* Add attribute if highlight group has changed */ if (lasttype != hlg) { sbpush(buf->lines[line].attrs, hl_line_attr(length, hlg)); lasttype = hlg; } /* Add the text and bump our length */ length += strlen(tok_data.data); } } } tokenizer_destroy(t); return 0; }
int malzmq_decode_message(malzmq_header_t *malzmq_header, mal_message_t *message, mal_decoder_t *decoder, void *cursor) { char b = ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++]; unsigned char version = (b >> 5) & 0x07; if (version != 1) return -1; int sduType = b & 0x1F; mal_interactiontype_t interaction_type = convert_to_interaction_type(sduType); if (interaction_type == -1) { clog_error(malzmq_logger, MALZMQ_BAD_INTERACTION_TYPE_MSG); return MALZMQ_BAD_INTERACTION_TYPE; } mal_message_set_interaction_type(message, interaction_type); mal_uoctet_t interaction_stage = convert_to_interaction_stage(sduType); if (interaction_stage == -1) { clog_error(malzmq_logger, MALZMQ_BAD_INTERACTION_STAGE_MSG); return MALZMQ_BAD_INTERACTION_STAGE; } mal_message_set_interaction_stage(message, interaction_stage); mal_ushort_t service_area = malbinary_read16(cursor) & 0xFFFF; mal_message_set_service_area(message, service_area); mal_ushort_t service = malbinary_read16(cursor) & 0xFFFF; mal_message_set_service(message, service); int operation = malbinary_read16(cursor) & 0xFFFF; mal_message_set_operation(message, operation); byte area_version = ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++]; mal_message_set_area_version(message, area_version); b = ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++]; bool is_error_message = (b >> 7) & 0x01; mal_message_set_is_error_message(message, is_error_message); int qoslevel = (b >> 4) & 0x07; mal_message_set_qoslevel(message, (mal_qoslevel_t) qoslevel); int session = (b >> 0) & 0x0F; mal_message_set_session(message, (mal_sessiontype_t) session); long transaction_id = malbinary_read64(cursor); mal_message_set_transaction_id(message, transaction_id); b = ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++]; char encoding_id_flag = (b >> 6) & 0x03; bool priority_flag = (b >> 5) & 0x01; bool timestamp_flag = (b >> 4) & 0x01; bool network_zone_flag = (b >> 3) & 0x01; bool session_name_flag = (b >> 2) & 0x01; bool domain_flag = (b >> 1) & 0x01; bool authentication_id_flag = b & 0x01; mal_uri_t *uri_from; malzmq_decode_uri(malzmq_header_get_mapping_directory(malzmq_header), decoder, cursor, &uri_from); mal_message_set_free_uri_from(message, true); mal_message_set_uri_from(message, uri_from); mal_uri_t *uri_to; malzmq_decode_uri(malzmq_header_get_mapping_directory(malzmq_header), decoder, cursor, &uri_to); mal_message_set_free_uri_to(message, true); mal_message_set_uri_to(message, uri_to); mal_uoctet_t encoding_id; if (encoding_id_flag == 3) { malbinary_decoder_decode_uoctet(decoder, cursor, &encoding_id); mal_message_set_encoding_id(message, encoding_id); } else { mal_message_set_encoding_id(message, encoding_id_flag); } mal_uinteger_t priority; if (priority_flag) { malbinary_decoder_decode_uinteger(decoder, cursor, &priority); } else { priority = malzmq_header_get_priority(malzmq_header); } mal_message_set_priority(message, priority); mal_time_t timestamp; if (timestamp_flag) { malzmq_decode_time(decoder, cursor, ×tamp); } mal_message_set_timestamp(message, timestamp); mal_identifier_t *network_zone; if (network_zone_flag) { malzmq_decode_identifier(malzmq_header_get_mapping_directory(malzmq_header), decoder, cursor, &network_zone); mal_message_set_free_network_zone(message, true); } else { network_zone = malzmq_header_get_network_zone(malzmq_header); mal_message_set_free_network_zone(message, false); } mal_message_set_network_zone(message, network_zone); mal_identifier_t *session_name; if (session_name_flag) { malzmq_decode_identifier(malzmq_header_get_mapping_directory(malzmq_header), decoder, cursor, &session_name); mal_message_set_free_session_name(message, true); } else { session_name = malzmq_header_get_session_name(malzmq_header); mal_message_set_free_session_name(message, false); } mal_message_set_session_name(message, session_name); mal_identifier_list_t *domain; if (domain_flag) { malzmq_decode_identifier_list(malzmq_header_get_mapping_directory(malzmq_header), decoder, cursor, &domain); mal_message_set_free_domain(message, true); } else { domain = malzmq_header_get_domain(malzmq_header); mal_message_set_free_domain(message, false); } mal_message_set_domain(message, domain); mal_blob_t *authentication_id; if (authentication_id_flag) { malbinary_decoder_decode_blob(decoder, cursor, &authentication_id); mal_message_set_free_authentication_id(message, true); } else { authentication_id = malzmq_header_get_authentication_id(malzmq_header); mal_message_set_free_authentication_id(message, false); } mal_message_set_authentication_id(message, authentication_id); unsigned int body_offset = ((malbinary_cursor_t *) cursor)->body_offset; unsigned int body_length = ((malbinary_cursor_t *) cursor)->body_length - body_offset; char *bytes = ((malbinary_cursor_t *) cursor)->body_ptr; char *body = NULL; if (body_length > 0) { // Copy the message in a newly allocated memory array. body = (char *) malloc(sizeof(char) * body_length); memcpy(body, bytes + body_offset, body_length); } // TODO (AF): Normally we should keep the body in the frame!! mal_message_set_body(message, body); mal_message_set_body_offset(message, 0); mal_message_set_body_length(message, body_length); return 0; }
int malzmq_encode_message(malzmq_header_t *malzmq_header, mal_message_t *message, mal_encoder_t *encoder, void *cursor) { clog_debug(mal_encoder_get_logger(encoder), "malzmq_encode_message()\n"); int sdu_type = convert_to_sdu_type( mal_message_get_interaction_type(message), mal_message_get_interaction_stage(message), mal_message_is_error_message(message)); if (sdu_type == -1) { clog_error(malzmq_logger, MALZMQ_BAD_SDU_TYPE_MSG); return MALZMQ_BAD_SDU_TYPE; } ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++] = (char) ((malzmq_header_get_version(malzmq_header) << 5) | sdu_type); malbinary_write16(mal_message_get_service_area(message), cursor); malbinary_write16(mal_message_get_service(message), cursor); malbinary_write16(mal_message_get_operation(message), cursor); ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++] = mal_message_get_area_version(message); ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++] = (char) ((mal_message_is_error_message(message) << 7) | (mal_message_get_qoslevel(message) << 4) | (mal_message_get_session(message))); malbinary_write64(mal_message_get_transaction_id(message), cursor); char encoding_id_flag; mal_uoctet_t encoding_id = mal_message_get_encoding_id(message); if (encoding_id < 3) encoding_id_flag = encoding_id; else encoding_id_flag = 3; bool priority_flag = malzmq_header_get_priority_flag(malzmq_header); bool timestamp_flag = malzmq_header_get_timestamp_flag(malzmq_header); bool network_zone_flag = malzmq_header_get_network_zone_flag(malzmq_header); bool session_name_flag = malzmq_header_get_session_name_flag(malzmq_header); bool domain_flag = malzmq_header_get_domain_flag(malzmq_header); bool authentication_id_flag = malzmq_header_get_authentication_id_flag(malzmq_header); ((malbinary_cursor_t *) cursor)->body_ptr[((malbinary_cursor_t *) cursor)->body_offset++] = (char) (encoding_id_flag << 6) | (priority_flag << 5) | (timestamp_flag << 4) | (network_zone_flag << 3) | (session_name_flag << 2) | (domain_flag << 1) | (authentication_id_flag << 0); // always encode 'URI From' and 'URI To' malzmq_encode_uri(mal_message_get_uri_from(message), malzmq_header_get_mapping_directory(malzmq_header), encoder, cursor); malzmq_encode_uri(mal_message_get_uri_to(message), malzmq_header_get_mapping_directory(malzmq_header), encoder, cursor); if (encoding_id_flag == 3) { malbinary_encoder_encode_uoctet(encoder, cursor, encoding_id); } if (priority_flag > 0) { malbinary_encoder_encode_uinteger(encoder, cursor, mal_message_get_priority(message)); } if (timestamp_flag != false) { malzmq_encode_time(encoder, cursor, mal_message_get_timestamp(message)); } if (network_zone_flag > 0) { malzmq_encode_identifier(mal_message_get_network_zone(message), malzmq_header_get_mapping_directory(malzmq_header), encoder, cursor); } if (session_name_flag > 0) { malzmq_encode_identifier(mal_message_get_session_name(message), malzmq_header_get_mapping_directory(malzmq_header), encoder, cursor); } if (domain_flag > 0) { malzmq_encode_identifier_list(mal_message_get_domain(message), malzmq_header_get_mapping_directory(malzmq_header), encoder, cursor); } if (authentication_id_flag > 0) { malbinary_encoder_encode_blob(encoder, cursor, mal_message_get_authentication_id(message)); } // Copy the body in the frame. unsigned int body_length = mal_message_get_body_length(message); if (body_length > 0) { char *body = mal_message_get_body(message); unsigned int body_offset = mal_message_get_body_offset(message); char *bytes = ((malbinary_cursor_t *) cursor)->body_ptr; unsigned int index = ((malbinary_cursor_t *) cursor)->body_offset; memcpy(bytes + index, body + body_offset, body_length); ((malbinary_cursor_t *) cursor)->body_offset += body_length; } return 0; }
struct tgdb *tgdb_initialize(const char *debugger, int argc, char **argv, int *debugger_fd, tgdb_callbacks callbacks) { /* Initialize the libtgdb context */ struct tgdb *tgdb = initialize_tgdb_context(callbacks); static struct annotations_parser_callbacks annotations_callbacks = { tgdb, tgdb_breakpoints_changed, tgdb_source_location_changed, tgdb_prompt_changed, tgdb_console_output, tgdb_command_error, tgdb_console_at_prompt }; char logs_dir[FSUTIL_PATH_MAX]; /* Create config directory */ if (tgdb_initialize_config_dir(tgdb, logs_dir) == -1) { clog_error(CLOG_CGDB, "tgdb_initialize error"); return NULL; } if (tgdb_initialize_logger_interface(tgdb, logs_dir) == -1) { printf("Could not initialize logger interface\n"); return NULL; } tgdb->debugger_pid = invoke_debugger(debugger, argc, argv, &tgdb->debugger_stdin, &tgdb->debugger_stdout, 0); /* Couldn't invoke process */ if (tgdb->debugger_pid == -1) return NULL; tgdb->c = commands_initialize(tgdb); tgdb->parser = annotations_parser_initialize(annotations_callbacks); tgdb_open_new_tty(tgdb, &tgdb->inferior_stdin, &tgdb->inferior_stdout); /* Need to get source information before breakpoint information otherwise * the TGDB_UPDATE_BREAKPOINTS event will be ignored in process_commands() * because there are no source files to add the breakpoints to. */ tgdb_request_current_location(tgdb); /* gdb may already have some breakpoints when it starts. This could happen * if the user puts breakpoints in there .gdbinit. * This makes sure that TGDB asks for the breakpoints on start up. */ tgdb_issue_request(tgdb, TGDB_REQUEST_BREAKPOINTS, true); /** * Query if disassemble supports the /s flag */ tgdb_issue_request(tgdb, TGDB_REQUEST_DATA_DISASSEMBLE_MODE_QUERY, true); *debugger_fd = tgdb->debugger_stdout; return tgdb; }
// This function is used by endpoint to receive message from zloop. int maltcp_ctx_recv_message(void *self, mal_endpoint_t *mal_endpoint, mal_message_t **message) { maltcp_ctx_t *maltcp_ctx = (maltcp_ctx_t *) self; maltcp_endpoint_data_t *endpoint_data = (maltcp_endpoint_data_t *) mal_endpoint_get_endpoint_data(mal_endpoint); int rc = 0; clog_debug(maltcp_logger, "maltcp_ctx_recv_message()\n"); zmsg_t *zmsg = zmsg_recv(endpoint_data->socket); if (zmsg) { size_t frames_count = zmsg_size(zmsg); clog_debug(maltcp_logger, "maltcp_ctx_recv_message: received zmsg (%d frames)\n", frames_count); // The first frame contains the peer URI. zframe_t *from = zmsg_pop(zmsg); char *peer_uri = NULL; if (from != NULL) { int len = zframe_size(from); peer_uri = (char *) malloc(len +1); strncpy(peer_uri, (char *)zframe_data(from), len); peer_uri[len] = '\0'; zframe_destroy(&from); } clog_debug(maltcp_logger, "maltcp_ctx_recv_message: peer_uri = %s\n", peer_uri); // The MAL message is in the second frame. // Now the frame is owned by us. zframe_t *frame = zmsg_pop(zmsg); size_t mal_msg_bytes_length = zframe_size(frame); clog_debug(maltcp_logger, "maltcp_ctx_recv_message: mal_msg_bytes_length=%d\n", mal_msg_bytes_length); // Does not copy the frame bytes in another array. byte *mal_msg_bytes = zframe_data(frame); *message = mal_message_new_void(); // MALTCP always uses the 'malbinary' encoding format for the messages header encoding (another // format may be used at the application layer for the message body). // Note: We could use virtual allocation and initialization functions from encoder // rather than malbinary interface. malbinary_cursor_t cursor; malbinary_cursor_init(&cursor, (char *) mal_msg_bytes, mal_msg_bytes_length, 0); mal_uinteger_t variable_length; // 'maltcp' encoding format of the MAL header if (maltcp_decode_message(maltcp_ctx->maltcp_header, *message, maltcp_ctx->decoder, &cursor, &variable_length) != 0) { clog_error(maltcp_logger, "maltcp_ctx_recv_message, cannot decode message\n"); return -1; } // Note: Currently the message length is always equal to the frame size. assert(mal_msg_bytes_length == (variable_length + FIXED_HEADER_LENGTH)); // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message. // currently the body is always copied in a newly allocated memory. // Destroy must free the tcp frame // mal_message_set_body_owner(*message, frame); // If the From URI field is not completely filled, we have to complete it with // the information from TCP/IP protocol. mal_uri_t *uri_from = mal_message_get_uri_from(*message); if (uri_from == NULL) { mal_message_set_uri_from(*message, peer_uri); mal_message_set_free_uri_from(*message, (1==1)); } else if (strncmp(uri_from, MALTCP_URI, sizeof MALTCP_URI -1) != 0) { if (uri_from[0] == '/') uri_from += 1; mal_uri_t *uri = (mal_uri_t *) malloc(strlen(peer_uri) + strlen(uri_from) +2); strcpy(uri, peer_uri); // Ensures presence of path separator (not added in maltcp_ctx_socket_receive). strcat(uri, "/"); strcat(uri, uri_from); mal_message_set_uri_from(*message, uri); mal_message_set_free_uri_from(*message, (1==1)); free(peer_uri); } else { // The complete URI is registered in the message header, use it. free(peer_uri); } // If the To URI field is not completely filled, we have to complete it. // TODO (AF): The To URI should never be completely filled!! mal_uri_t *uri_to = mal_message_get_uri_to(*message); if ((uri_to == NULL) || (strncmp(uri_to, MALTCP_URI, sizeof MALTCP_URI -1) != 0)) { mal_message_set_uri_to(*message, mal_endpoint_get_uri(endpoint_data->mal_endpoint)); mal_message_set_free_uri_to(*message, (1!=1)); } clog_debug(maltcp_logger, "maltcp_ctx_recv_message: "); if (clog_is_loggable(maltcp_logger, CLOG_DEBUG_LEVEL)) mal_message_print(*message); clog_debug(maltcp_logger, "\n"); // Verify if the message could be delivered and destroy it otherwise. if (endpoint_data->mal_endpoint) { bool message_delivered = false; mal_uri_t *endpoint_uri = mal_endpoint_get_uri(endpoint_data->mal_endpoint); if (strcmp(maltcp_get_service_from_uri(endpoint_uri), maltcp_get_service_from_uri(uri_to)) == 0) message_delivered = true; clog_debug(maltcp_logger, "maltcp_ctx_recv_message: message_delivered=%d\n", message_delivered); if (!message_delivered) { clog_debug(maltcp_logger, "maltcp_ctx_recv_message: destroy MAL message\n", uri_to); mal_message_destroy(message, maltcp_ctx->mal_ctx); } } // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message. // currently the body is always copied in a newly allocated memory. zframe_destroy(&frame); } else { clog_debug(maltcp_logger, "maltcp_ctx_recv_message(): NULL\n"); } return rc; }
// Must be compliant with MAL virtual function: void *self int maltcp_ctx_send_message(void *self, mal_endpoint_t *mal_endpoint, mal_message_t *mal_message) { maltcp_ctx_t *maltcp_ctx = (maltcp_ctx_t *) self; if (clog_is_loggable(maltcp_logger, CLOG_INFO_LEVEL)) { clog_info(maltcp_logger, "maltcp_ctx_send_message:\n"); mal_message_print(mal_message); clog_info(maltcp_logger, "\n"); } int rc = 0; mal_uri_t *uri_to = mal_message_get_uri_to(mal_message); clog_debug(maltcp_logger, "maltcp_ctx_send_message: uri_to=%s\n", uri_to); char *peer_uri = maltcp_get_base_uri(uri_to); clog_debug(maltcp_logger, "maltcp_ctx_send_message: peer_uri=%s\n", peer_uri); maltcp_ctx_connection_t *cnx_ptr = maltcp_ctx_socket_connect(maltcp_ctx, peer_uri); if (cnx_ptr == NULL) { clog_error(maltcp_logger, "maltcp_ctx_send_message: cannot create connection for %s.\n", peer_uri); free(peer_uri); return -1; } free(peer_uri); // Note: We could use virtual allocation and initialization functions from encoder // rather than malbinary interface. malbinary_cursor_t cursor; malbinary_cursor_reset(&cursor); // TODO: In a first time we should separate the header and body size in order to send them // in separate frames. In a second time we should cut the message in multiples frames. // maltcp_add_message_encoding_length should not add body_length to encoding length // bytes should content uniquely the header // maltcp_encode_message should not copy the body to the bytes array // we should creates and send 2 frames // 'maltcp' encoding format of the MAL header rc = maltcp_add_message_encoding_length(maltcp_ctx->maltcp_header, mal_message, maltcp_ctx->encoder, &cursor); if (rc < 0) return rc; clog_debug(maltcp_logger, "maltcp_ctx: encoding_length=%d\n", malbinary_cursor_get_length(&cursor)); // Note: We could use virtual allocation and initialization functions from encoder // rather than malbinary interface. malbinary_cursor_init(&cursor, (char *) malloc(malbinary_cursor_get_length(&cursor)), malbinary_cursor_get_length(&cursor), 0); clog_debug(maltcp_logger, "maltcp_ctx: mal_message_encode_malbinary\n"); // 'maltcp' encoding format of the MAL header rc = maltcp_encode_message(maltcp_ctx->maltcp_header, mal_message, maltcp_ctx->encoder, &cursor); if (rc < 0) return rc; assert(cursor.body_length == cursor.body_offset); clog_debug(maltcp_logger, "maltcp_ctx: message is encoded: %d bytes\n", malbinary_cursor_get_offset(&cursor)); // send the message if (maltcp_ctx_socket_send(cnx_ptr, &cursor) < 0) return -1; return 0; }
// This function is called when a message is ready to be read on the specified //connection. The connection is registered with the URI if needed. int maltcp_ctx_socket_receive(zloop_t *loop, zmq_pollitem_t *poller, void *arg) { clog_debug(maltcp_logger, "maltcp_ctx_socket_receive\n"); maltcp_ctx_t *self = (maltcp_ctx_t *) arg; struct sockaddr src_addr; socklen_t addr_size = sizeof(struct sockaddr_in); if (getpeername(poller->fd, (struct sockaddr *)&src_addr, &addr_size) != 0) { clog_error(maltcp_logger, "maltcp_ctx_socket_receive: getpeername failed\n"); return -1; } char src_ipstr[INET6_ADDRSTRLEN]; int src_port; if (src_addr.sa_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *)&src_addr; src_port = ntohs(s->sin_port); inet_ntop(AF_INET, &s->sin_addr, src_ipstr, sizeof src_ipstr); } else { // AF_INET6 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&src_addr; src_port = ntohs(s->sin6_port); inet_ntop(AF_INET6, &s->sin6_addr, src_ipstr, sizeof src_ipstr); } mal_uri_t peer_uri[strlen(src_ipstr) + 10 + 10 + 1]; sprintf((char*) peer_uri, "%s%s:%d", MALTCP_URI, src_ipstr, src_port); clog_debug(maltcp_logger, "maltcp_ctx: TCP server socket receive from URI: %s\n", peer_uri); char header[FIXED_HEADER_LENGTH]; int nb = 0; while (nb < FIXED_HEADER_LENGTH) { int nbread = recv(poller->fd, &header[nb], FIXED_HEADER_LENGTH-nb, 0); if (nbread == 0) { clog_warning(maltcp_logger, "maltcp_ctx_socket_receive: TCP connection (%d) closed\n", poller->fd); maltcp_ctx_connection_remove_socket(self, poller->fd); zloop_poller_end(loop, poller); close(poller->fd); return 0; } if (nbread <0) { clog_error(maltcp_logger, "maltcp_ctx_socket_receive: Error reading header on TCP connection\n"); maltcp_ctx_connection_remove_socket(self, poller->fd); zloop_poller_end(loop, poller); close(poller->fd); return -1; } nb += nbread; } // First read, get the message size in the header int msg_size = maltcp_decode_variable_length(header, nb) + FIXED_HEADER_LENGTH; clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: should read = %d bytes\n", msg_size); // Allocate the message and copy header char* msg = (char*) malloc(msg_size); memcpy(msg, header, FIXED_HEADER_LENGTH); // Read the whole message while (nb < msg_size) { int nbread = recv(poller->fd, &msg[nb], msg_size-nb, 0); if (nbread <=0) { clog_error(maltcp_logger, "maltcp_ctx_socket_receive: Error reading message on TCP connection\n"); maltcp_ctx_connection_remove_socket(self, poller->fd); zloop_poller_end(loop, poller); close(poller->fd); free(msg); return -1; } nb += nbread; } clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: message received, size = %d\n", msg_size); // Get URIs from message and register connection if needed mal_uri_t *uri_to; mal_uri_t *uri_from; if (maltcp_decode_uris(self->maltcp_header, self->decoder, msg, msg_size, &uri_to, &uri_from) != 0) { clog_error(maltcp_logger, "maltcp_ctx_socket_receive, could not decode uri_to\n"); return -1; } clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: uri_to=%s uri_from=%s\n", uri_to, uri_from); if ((uri_from != NULL) && (strncmp(uri_from, MALTCP_URI, sizeof MALTCP_URI -1) == 0)) { // The complete URI is registered in the message header, use it. int len = strlen(uri_from); char *ptr = strchr(uri_from +sizeof MALTCP_URI, '/'); if (ptr != NULL) len = ptr-uri_from; char uri[len+1]; strncpy(uri, uri_from, len); uri[len] = '\0'; clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: register#1 %s\n", uri); // Register the connection if needed maltcp_ctx_connection_register_incoming(self, poller->fd, uri); } else { clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: register#2 %s\n", peer_uri); // Register the connection if needed maltcp_ctx_connection_register_incoming(self, poller->fd, peer_uri); } // Forward the message to the appropriate endpoint. // Note: Normally the message will be deleted by the appropriate endpoint. // What happens if no endpoint reads this message? It seems that Router socket // discard messages if there are no readers. assert(uri_to != NULL); // Get the service part of URI needed to route the message. mal_uri_t *short_uri_to = maltcp_get_service_from_uri(uri_to); int rc = zmq_send(self->endpoints_socket, short_uri_to, strlen(short_uri_to), ZMQ_SNDMORE); assert(rc == strlen(short_uri_to)); clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: send identity (%d bytes) to endpoint %s\n", rc, short_uri_to); // Send the peer URI rc = zmq_send(self->endpoints_socket, peer_uri, strlen(peer_uri), ZMQ_SNDMORE); assert(rc == strlen(peer_uri)); clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: send peer URI (%d bytes) to endpoint %s\n", rc, peer_uri); // Send the message clog_debug(maltcp_logger, "maltcp_ctx_socket_receive: send message (%d bytes) to endpoint %s\n", msg_size, short_uri_to); rc = zmq_send(self->endpoints_socket, msg, msg_size, ZMQ_DONTWAIT); assert(rc == msg_size); clog_debug(maltcp_logger, "maltcp_ctx: message handled.\n"); // Destroy URIs: Be careful, short_uri_to is simply a pointer in uri_to. mal_uri_destroy(&uri_to); mal_uri_destroy(&uri_from); return 0; }