int pn_message_load_amqp(pn_message_t *msg, const char *data, size_t size) { if (!msg) return PN_ARG_ERR; if (!msg->body) { msg->body = pn_data(64); } pn_parser_t *parser = pn_message_parser(msg); while (true) { pn_data_clear(msg->body); pn_atoms_t atoms = pn_data_available(msg->body); int err = pn_parser_parse(parser, data, &atoms); if (err == PN_OVERFLOW) { err = pn_data_grow(msg->body); if (err) return err; continue; } else if (err) { return err; } else { return pn_data_resize(msg->body, atoms.size); } } }
static pn_message_t *build_request_message(pn_message_t *message, const char *command, const char *to, const char *reply_to, const char *new_fortune, unsigned int ttl) { int rc; pn_message_set_address( message, to ); if (reply_to) { LOG("setting reply-to %s\n", reply_to); rc = pn_message_set_reply_to( message, reply_to ); check(rc == 0, "pn_message_set_reply_to() failed"); } pn_message_set_delivery_count( message, 0 ); if (ttl) pn_message_set_ttl( message, ttl * 1000 ); pn_data_t *body = pn_message_body(message); pn_data_clear( body ); rc = pn_data_fill( body, "{SSSSSS}", "type", "request", "command", command, "value", (new_fortune) ? new_fortune : "" ); check( rc == 0, "Failure to create request message" ); return message; }
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; }
int buffer(int argc, char **argv) { pn_buffer_t *buf = pn_buffer(16); pn_buffer_append(buf, "abcd", 4); pn_buffer_print(buf); printf("\n"); pn_buffer_prepend(buf, "012", 3); pn_buffer_print(buf); printf("\n"); pn_buffer_prepend(buf, "z", 1); pn_buffer_print(buf); printf("\n"); pn_buffer_append(buf, "efg", 3); pn_buffer_print(buf); printf("\n"); pn_buffer_append(buf, "hijklm", 6); pn_buffer_print(buf); printf("\n"); pn_buffer_defrag(buf); pn_buffer_print(buf); printf("\n"); pn_buffer_trim(buf, 1, 1); pn_buffer_print(buf); printf("\n"); pn_buffer_trim(buf, 4, 0); pn_buffer_print(buf); printf("\n"); pn_buffer_clear(buf); pn_buffer_print(buf); printf("\n"); pn_buffer_free(buf); pn_data_t *data = pn_data(16); int err = pn_data_fill(data, "Ds[iSi]", "desc", 1, "two", 3); if (err) { printf("%s\n", pn_code(err)); } pn_data_print(data); printf("\n"); pn_bytes_t str; err = pn_data_scan(data, "D.[.S.]", &str); if (err) { printf("%s\n", pn_code(err)); } else { printf("%.*s\n", (int) str.size, str.start); } pn_data_clear(data); pn_data_fill(data, "DL[SIonn?DL[S]?DL[S]nnI]", ATTACH, "asdf", 1, true, true, SOURCE, "queue", true, TARGET, "queue", 0); pn_data_print(data); printf("\n"); pn_data_free(data); return 0; }
int pn_message_encode(pn_message_t *msg, char *bytes, size_t *size) { if (!msg || !bytes || !size || !*size) return PN_ARG_ERR; if (!msg->data) { msg->data = pn_data(64); } if (!msg->body) { msg->body = pn_data(64); } int err = pn_data_clear(msg->data); if (err) return err; err = pn_data_fill(msg->data, "DL[oBIoI]", HEADER, msg->durable, msg->priority, msg->ttl, msg->first_acquirer, msg->delivery_count); if (err) return err; err = pn_data_fill(msg->data, "DL[nzSSSnssLLSiS]", PROPERTIES, pn_buffer_bytes(msg->user_id), pn_buffer_str(msg->address), pn_buffer_str(msg->subject), pn_buffer_str(msg->reply_to), pn_buffer_str(msg->content_type), pn_buffer_str(msg->content_encoding), msg->expiry_time, msg->creation_time, pn_buffer_str(msg->group_id), msg->group_sequence, pn_buffer_str(msg->reply_to_group_id)); if (err) return err; size_t remaining = *size; size_t encoded = remaining; err = pn_data_encode(msg->data, bytes, &encoded); if (err) return err; bytes += encoded; remaining -= encoded; encoded = remaining; err = pn_data_encode(msg->body, bytes, &encoded); if (err) return err; bytes += encoded; remaining -= encoded; *size -= remaining; return 0; }
void pn_message_clear(pn_message_t *msg) { msg->durable = false; msg->priority = PN_DEFAULT_PRIORITY; msg->ttl = 0; msg->first_acquirer = false; msg->delivery_count = 0; msg->id.type = PN_NULL; if (msg->user_id) pn_buffer_clear(msg->user_id); if (msg->address) pn_buffer_clear(msg->address); if (msg->subject) pn_buffer_clear(msg->subject); if (msg->reply_to) pn_buffer_clear(msg->reply_to); msg->correlation_id.type = PN_NULL; if (msg->content_type) pn_buffer_clear(msg->content_type); if (msg->content_encoding) pn_buffer_clear(msg->content_encoding); msg->expiry_time = 0; msg->creation_time = 0; if (msg->group_id) pn_buffer_clear(msg->group_id); msg->group_sequence = 0; if (msg->reply_to_group_id) pn_buffer_clear(msg->reply_to_group_id); if (msg->data) pn_data_clear(msg->data); if (msg->body) pn_data_clear(msg->body); }
int pn_dispatch_frame(pn_dispatcher_t *disp, pn_frame_t frame) { if (frame.size == 0) { // ignore null frames if (disp->trace & PN_TRACE_FRM) pn_transport_logf(disp->transport, "%u <- (EMPTY FRAME)\n", frame.channel); return 0; } ssize_t dsize = pn_data_decode(disp->args, frame.payload, frame.size); if (dsize < 0) { pn_string_format(disp->scratch, "Error decoding frame: %s %s\n", pn_code(dsize), pn_error_text(pn_data_error(disp->args))); pn_quote(disp->scratch, frame.payload, frame.size); pn_transport_log(disp->transport, pn_string_get(disp->scratch)); return dsize; } disp->channel = frame.channel; // XXX: assuming numeric uint64_t lcode; bool scanned; int e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode); if (e) { pn_transport_log(disp->transport, "Scan error"); return e; } if (!scanned) { pn_transport_log(disp->transport, "Error dispatching frame"); return PN_ERR; } uint8_t code = lcode; disp->code = code; disp->size = frame.size - dsize; if (disp->size) disp->payload = frame.payload + dsize; pn_do_trace(disp, disp->channel, IN, disp->args, disp->payload, disp->size); pn_action_t *action = disp->actions[code]; int err = action(disp); disp->channel = 0; disp->code = 0; pn_data_clear(disp->args); disp->size = 0; disp->payload = NULL; return err; }
bool encoder::encode(char* buffer, size_t& size) { save_state ss(pn_cast(this)); // In case of error ssize_t result = pn_data_encode(pn_cast(this), buffer, size); if (result == PN_OVERFLOW) { result = pn_data_encoded_size(pn_cast(this)); if (result >= 0) { size = result; return false; } } check(result, pn_cast(this)); size = result; ss.cancel(); // Don't restore state, all is well. pn_data_clear(pn_cast(this)); return true; }
int pn_message_decode(pn_message_t *msg, const char *bytes, size_t size) { if (!msg || !bytes || !size) return PN_ARG_ERR; if (!msg->data) { msg->data = pn_data(64); } if (!msg->body) { msg->body = pn_data(64); } pn_data_clear(msg->body); while (size) { size_t copy = size; pn_data_clear(msg->data); int err = pn_data_decode(msg->data, (char *) bytes, ©); if (err) return err; size -= copy; bytes += copy; bool scanned; uint64_t desc; err = pn_data_scan(msg->data, "D?L.", &scanned, &desc); if (err) return err; if (!scanned){ desc = 0; } switch (desc) { case HEADER: pn_data_scan(msg->data, "D.[oBIoI]", &msg->durable, &msg->priority, &msg->ttl, &msg->first_acquirer, &msg->delivery_count); break; case PROPERTIES: { pn_bytes_t user_id, address, subject, reply_to, ctype, cencoding, group_id, reply_to_group_id; err = pn_data_scan(msg->data, "D.[.zSSS.ssLLSiS]", &user_id, &address, &subject, &reply_to, &ctype, &cencoding, &msg->expiry_time, &msg->creation_time, &group_id, &msg->group_sequence, &reply_to_group_id); if (err) return err; err = pn_buffer_set_bytes(&msg->user_id, user_id); if (err) return err; err = pn_buffer_set_strn(&msg->address, address.start, address.size); if (err) return err; err = pn_buffer_set_strn(&msg->subject, subject.start, subject.size); if (err) return err; err = pn_buffer_set_strn(&msg->reply_to, reply_to.start, reply_to.size); if (err) return err; err = pn_buffer_set_strn(&msg->content_type, ctype.start, ctype.size); if (err) return err; err = pn_buffer_set_strn(&msg->content_encoding, cencoding.start, cencoding.size); if (err) return err; err = pn_buffer_set_strn(&msg->group_id, group_id.start, group_id.size); if (err) return err; err = pn_buffer_set_strn(&msg->reply_to_group_id, reply_to_group_id.start, reply_to_group_id.size); if (err) return err; } break; case DELIVERY_ANNOTATIONS: case MESSAGE_ANNOTATIONS: break; default: { pn_data_t *data = msg->body; msg->body = msg->data; msg->data = data; err = pn_data_intern(msg->body); if (err) return err; } break; } } return pn_data_clear(msg->data); }
int main(int argc, char** argv) { const char *address = "localhost"; const char *msgtext = "Hello World!"; const char *container = "SendExample"; int c; pn_message_t *message = NULL; pn_data_t *body = NULL; pn_reactor_t *reactor = NULL; pn_url_t *url = NULL; pn_connection_t *conn = NULL; /* Create a handler for the connection's events. event_handler() will be * called for each event and delete_handler will be called when the * connection is released. The handler will allocate an app_data_t * instance which can be accessed when the event_handler is called. */ pn_handler_t *handler = pn_handler_new(event_handler, sizeof(app_data_t), delete_handler); /* set up the application data with defaults */ app_data_t *app_data = GET_APP_DATA(handler); memset(app_data, 0, sizeof(app_data_t)); app_data->count = 1; app_data->target = "examples"; /* Attach the pn_handshaker() handler. This handler deals with endpoint * events from the peer so we don't have to. */ { pn_handler_t *handshaker = pn_handshaker(); pn_handler_add(handler, handshaker); pn_decref(handshaker); } /* command line options */ opterr = 0; while((c = getopt(argc, argv, "i:a:c:t:nhq")) != -1) { switch(c) { case 'h': usage(); break; case 'a': address = optarg; break; case 'c': app_data->count = atoi(optarg); if (app_data->count < 1) usage(); break; case 't': app_data->target = optarg; break; case 'n': app_data->anon = 1; break; case 'i': container = optarg; break; case 'q': quiet = 1; break; default: usage(); break; } } if (optind < argc) msgtext = argv[optind]; // create a single message and pre-encode it so we only have to do that // once. All transmits will use the same pre-encoded message simply for // speed. // message = pn_message(); pn_message_set_address(message, app_data->target); body = pn_message_body(message); pn_data_clear(body); // This message's body contains a single string if (pn_data_fill(body, "S", msgtext)) { fprintf(stderr, "Error building message!\n"); exit(1); } pn_data_rewind(body); { // encode the message, expanding the encode buffer as needed // size_t len = 128; char *buf = (char *)malloc(len); int rc = 0; do { rc = pn_message_encode(message, buf, &len); if (rc == PN_OVERFLOW) { free(buf); len *= 2; buf = (char *)malloc(len); } } while (rc == PN_OVERFLOW); app_data->msg_len = len; app_data->msg_data = buf; } pn_decref(message); // message no longer needed reactor = pn_reactor(); url = pn_url_parse(address); if (url == NULL) { fprintf(stderr, "Invalid host address %s\n", address); exit(1); } conn = pn_reactor_connection_to_host(reactor, pn_url_get_host(url), pn_url_get_port(url), handler); pn_decref(url); pn_decref(handler); // the container name should be unique for each client pn_connection_set_container(conn, container); // wait up to 5 seconds for activity before returning from // pn_reactor_process() pn_reactor_set_timeout(reactor, 5000); pn_reactor_start(reactor); while (pn_reactor_process(reactor)) { /* Returns 'true' until the connection is shut down. * pn_reactor_process() will return true at least once every 5 seconds * (due to the timeout). If no timeout was configured, * pn_reactor_process() returns as soon as it finishes processing all * pending I/O and events. Once the connection has closed, * pn_reactor_process() will return false. */ } pn_decref(reactor); 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; }