Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
// 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;
}
Beispiel #4
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;
}
Beispiel #5
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");
  }
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
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;
}
Beispiel #10
0
/* 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;
}
Beispiel #11
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;
}
Beispiel #12
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;
}
Beispiel #13
0
/* 
 * 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;
}
Beispiel #14
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;
}
Beispiel #15
0
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;
  }
}
Beispiel #16
0
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;
}
Beispiel #17
0
// 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;
}
Beispiel #18
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;
}
Beispiel #19
0
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();
    }

}
Beispiel #20
0
/* 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;
}
Beispiel #21
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;
}
Beispiel #22
0
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;
}
Beispiel #23
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;
}
Beispiel #24
0
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;
}
Beispiel #25
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, &timestamp);
  }
  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;
}
Beispiel #26
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;
}
Beispiel #27
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;
}
Beispiel #28
0
// 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;
}
Beispiel #29
0
// 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;
}
Beispiel #30
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;
}