void sender_context_init(sender_context_t *sc, Options_t *opts, Statistics_t *stats) { sc->opts = opts; sc->stats = stats; sc->sent = 0; sc->received = 0; sc->id.type = PN_ULONG; sc->reply_message = 0; // 4096 extra bytes should easily cover the message metadata sc->encoded_data_size = sc->opts->msg_size + 4096; sc->encoded_data = (char *)calloc(1, sc->encoded_data_size); check(sc->encoded_data, "failed to allocate encoding buffer"); sc->container_id = pn_string("reactor-send"); // prefer uuid-like name sc->reply_message = (sc->opts->get_replies) ? pn_message() : 0; sc->message = pn_message(); check(sc->message, "failed to allocate a message"); pn_string_t *rpto = pn_string("amqp://"); pn_string_addf(rpto, "%s", pn_string_get(sc->container_id)); pn_message_set_reply_to(sc->message, pn_string_get(rpto)); pn_free(rpto); pn_data_t *body = pn_message_body(sc->message); // borrow the encoding buffer this one time char *data = sc->encoded_data; pn_data_put_binary(body, pn_bytes(sc->opts->msg_size, data)); check(sc->opts->targets.count > 0, "no specified address"); sc->send_url = pn_url_parse(sc->opts->targets.addresses[0]); const char *host = pn_url_get_host(sc->send_url); const char *port = pn_url_get_port(sc->send_url); sc->hostname = pn_string(host); if (port && strlen(port)) pn_string_addf(sc->hostname, ":%s", port); }
int pni_subscription_set_address(pn_subscription_t *sub, const char *address) { assert(sub); if (!address) return 0; bool absolute = strncmp(address, "amqp:", 5) == 0; if (absolute) { return pn_string_set(sub->address, address); } else { pn_string_set(sub->address, ""); bool scheme = pn_string_get(sub->scheme); if (scheme) { int e = pn_string_addf(sub->address, "%s:", pn_string_get(sub->scheme)); if (e) return e; } if (pn_string_get(sub->host)) { int e = pn_string_addf(sub->address, scheme ? "//%s" : "%s", pn_string_get(sub->host)); if (e) return e; } if (pn_string_get(sub->port)) { int e = pn_string_addf(sub->address, ":%s", pn_string_get(sub->port)); if (e) return e; } return pn_string_addf(sub->address, "/%s", address); } }
static int pn_url_inspect(void *obj, pn_string_t *dst) { pn_url_t *url = (pn_url_t *) obj; int err = 0; err = pn_string_addf(dst, "Url("); if (err) return err; err = pn_inspect(pn_url_string(url), dst); if (err) return err; return pn_string_addf(dst, ")"); }
/** URL-encode src and append to dst. */ static void pni_urlencode(pn_string_t *dst, const char* src) { static const char *bad = "@:/"; if (!src) return; const char *i = src; const char *j = strpbrk(i, bad); while (j) { pn_string_addf(dst, "%.*s", (int)(j-i), i); pn_string_addf(dst, "%%%02X", (int)*j); i = j + 1; j = strpbrk(i, bad); } pn_string_addf(dst, "%s", i); }
static int pn_list_inspect(void *obj, pn_string_t *dst) { assert(obj); pn_list_t *list = (pn_list_t *) obj; int err = pn_string_addf(dst, "["); if (err) return err; size_t n = pn_list_size(list); for (size_t i = 0; i < n; i++) { if (i > 0) { err = pn_string_addf(dst, ", "); if (err) return err; } err = pn_class_inspect(list->clazz, pn_list_get(list, i), dst); if (err) return err; } return pn_string_addf(dst, "]"); }
static int pn_collector_inspect(pn_collector_t *collector, pn_string_t *dst) { assert(collector); int err = pn_string_addf(dst, "EVENTS["); if (err) return err; pn_event_t *event = collector->head; bool first = true; while (event) { if (first) { first = false; } else { err = pn_string_addf(dst, ", "); if (err) return err; } err = pn_inspect(event, dst); if (err) return err; event = event->next; } return pn_string_addf(dst, "]"); }
static void test_string_addf(void) { pn_string_t *str = pn_string("hello "); assert(str); int err = pn_string_addf(str, "%s", "this is a string that should be long " "enough to force growth but just in case we'll " "tack this other really long string on for the " "heck of it"); assert(err == 0); pn_free(str); }
static int pn_event_inspect(pn_event_t *event, pn_string_t *dst) { assert(event); assert(dst); const char *name = pn_event_type_name(event->type); int err; if (name) { err = pn_string_addf(dst, "(%s", pn_event_type_name(event->type)); } else { err = pn_string_addf(dst, "(<%u>", (unsigned int) event->type); } if (err) return err; if (event->context) { err = pn_string_addf(dst, ", "); if (err) return err; err = pn_class_inspect(event->clazz, event->context, dst); if (err) return err; } return pn_string_addf(dst, ")"); }
int pn_post_frame(pn_dispatcher_t *disp, uint16_t ch, const char *fmt, ...) { va_list ap; va_start(ap, fmt); pn_data_clear(disp->output_args); int err = pn_data_vfill(disp->output_args, fmt, ap); va_end(ap); if (err) { pn_transport_logf(disp->transport, "error posting frame: %s, %s: %s", fmt, pn_code(err), pn_error_text(pn_data_error(disp->output_args))); return PN_ERR; } pn_do_trace(disp, ch, OUT, disp->output_args, disp->output_payload, disp->output_size); encode_performatives: pn_buffer_clear( disp->frame ); pn_bytes_t buf = pn_buffer_bytes( disp->frame ); buf.size = pn_buffer_available( disp->frame ); ssize_t wr = pn_data_encode( disp->output_args, buf.start, buf.size ); if (wr < 0) { if (wr == PN_OVERFLOW) { pn_buffer_ensure( disp->frame, pn_buffer_available( disp->frame ) * 2 ); goto encode_performatives; } pn_transport_logf(disp->transport, "error posting frame: %s", pn_code(wr)); return PN_ERR; } pn_frame_t frame = {disp->frame_type}; frame.channel = ch; frame.payload = buf.start; frame.size = wr; size_t n; while (!(n = pn_write_frame(disp->output + disp->available, disp->capacity - disp->available, frame))) { disp->capacity *= 2; disp->output = (char *) realloc(disp->output, disp->capacity); } disp->output_frames_ct += 1; if (disp->trace & PN_TRACE_RAW) { pn_string_set(disp->scratch, "RAW: \""); pn_quote(disp->scratch, disp->output + disp->available, n); pn_string_addf(disp->scratch, "\""); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); } disp->available += n; return 0; }
static void pn_do_trace(pn_dispatcher_t *disp, uint16_t ch, pn_dir_t dir, pn_data_t *args, const char *payload, size_t size) { if (disp->trace & PN_TRACE_FRM) { pn_string_format(disp->scratch, "%u %s ", ch, dir == OUT ? "->" : "<-"); pn_inspect(args, disp->scratch); if (size) { char buf[1024]; int e = pn_quote_data(buf, 1024, payload, size); pn_string_addf(disp->scratch, " (%" PN_ZU ") \"%s\"%s", size, buf, e == PN_OVERFLOW ? "... (truncated)" : ""); } pn_transport_log(disp->transport, pn_string_get(disp->scratch)); } }
/** Return the string form of a URL. */ PN_EXTERN const char *pn_url_str(pn_url_t *url) { if (pn_string_get(url->str) == NULL) { pn_string_set(url->str, ""); if (url->scheme) pn_string_addf(url->str, "%s://", url->scheme); if (url->username) pni_urlencode(url->str, url->username); if (url->password) { pn_string_addf(url->str, ":"); pni_urlencode(url->str, url->password); } if (url->username || url->password) pn_string_addf(url->str, "@"); if (url->host) { if (strchr(url->host, ':')) pn_string_addf(url->str, "[%s]", url->host); else pn_string_addf(url->str, "%s", url->host); } if (url->port) pn_string_addf(url->str, ":%s", url->port); if (url->path) pn_string_addf(url->str, "/%s", url->path); } return pn_string_get(url->str); }
// Received client side int pn_do_mechanisms(pn_transport_t *transport, uint8_t frame_type, uint16_t channel, pn_data_t *args, const pn_bytes_t *payload) { pni_sasl_t *sasl = transport->sasl; // If we already pretended we got the ANONYMOUS mech then ignore if (sasl->last_state==SASL_PRETEND_OUTCOME) return 0; // This scanning relies on pn_data_scan leaving the pn_data_t cursors // where they are after finishing the scan int err = pn_data_scan(args, "D.[@["); if (err) return err; pn_string_t *mechs = pn_string(""); // Now keep checking for end of array and pull a symbol while(pn_data_next(args)) { pn_bytes_t s = pn_data_get_symbol(args); if (pni_included_mech(transport->sasl->included_mechanisms, s)) { pn_string_addf(mechs, "%*s ", (int)s.size, s.start); } } if (pn_string_size(mechs)) { pn_string_buffer(mechs)[pn_string_size(mechs)-1] = 0; } if (pni_init_client(transport) && pni_process_mechanisms(transport, pn_string_get(mechs))) { pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); } else { sasl->outcome = PN_SASL_PERM; pni_sasl_set_desired_state(transport, SASL_RECVED_OUTCOME_FAIL); } pn_free(mechs); return 0; }
int pn_post_transfer_frame(pn_dispatcher_t *disp, uint16_t ch, uint32_t handle, pn_sequence_t id, const pn_bytes_t *tag, uint32_t message_format, bool settled, bool more, pn_sequence_t frame_limit) { bool more_flag = more; int framecount = 0; // create preformatives, assuming 'more' flag need not change compute_performatives: pn_data_clear(disp->output_args); int err = pn_data_fill(disp->output_args, "DL[IIzIoo]", TRANSFER, handle, id, tag->size, tag->start, message_format, settled, more_flag); if (err) { pn_transport_logf(disp->transport, "error posting transfer frame: %s: %s", pn_code(err), pn_error_text(pn_data_error(disp->output_args))); return PN_ERR; } do { // send as many frames as possible without changing the 'more' flag... encode_performatives: pn_buffer_clear( disp->frame ); pn_bytes_t buf = pn_buffer_bytes( disp->frame ); buf.size = pn_buffer_available( disp->frame ); ssize_t wr = pn_data_encode(disp->output_args, buf.start, buf.size); if (wr < 0) { if (wr == PN_OVERFLOW) { pn_buffer_ensure( disp->frame, pn_buffer_available( disp->frame ) * 2 ); goto encode_performatives; } pn_transport_logf(disp->transport, "error posting frame: %s", pn_code(wr)); return PN_ERR; } buf.size = wr; // check if we need to break up the outbound frame size_t available = disp->output_size; if (disp->remote_max_frame) { if ((available + buf.size) > disp->remote_max_frame - 8) { available = disp->remote_max_frame - 8 - buf.size; if (more_flag == false) { more_flag = true; goto compute_performatives; // deal with flag change } } else if (more_flag == true && more == false) { // caller has no more, and this is the last frame more_flag = false; goto compute_performatives; } } if (pn_buffer_available( disp->frame ) < (available + buf.size)) { // not enough room for payload - try again... pn_buffer_ensure( disp->frame, available + buf.size ); goto encode_performatives; } pn_do_trace(disp, ch, OUT, disp->output_args, disp->output_payload, available); memmove( buf.start + buf.size, disp->output_payload, available); disp->output_payload += available; disp->output_size -= available; buf.size += available; pn_frame_t frame = {disp->frame_type}; frame.channel = ch; frame.payload = buf.start; frame.size = buf.size; size_t n; while (!(n = pn_write_frame(disp->output + disp->available, disp->capacity - disp->available, frame))) { disp->capacity *= 2; disp->output = (char *) realloc(disp->output, disp->capacity); } disp->output_frames_ct += 1; framecount++; if (disp->trace & PN_TRACE_RAW) { pn_string_set(disp->scratch, "RAW: \""); pn_quote(disp->scratch, disp->output + disp->available, n); pn_string_addf(disp->scratch, "\""); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); } disp->available += n; } while (disp->output_size > 0 && framecount < frame_limit); disp->output_payload = NULL; return framecount; }