/** Generate array of name-value pairs */ APT_DECLARE(apt_bool_t) apt_pair_array_generate(const apt_pair_arr_t *arr, apt_str_t *str, apr_pool_t *pool) { int p, v = 0; struct iovec vec[512]; const apt_pair_t *pair; static const int MAX_VECS = sizeof(vec) / sizeof(*vec); static const struct iovec IOV_SEMICOLON = {";", 1}; static const struct iovec IOV_EQUALS = {"=", 1}; for (p = 0; p < arr->nelts; p++) { pair = (apt_pair_t*)arr->elts + p; if (!pair->name.length) continue; if (v) { if (v >= MAX_VECS) return FALSE; vec[v++] = IOV_SEMICOLON; } if (v + (pair->value.length ? 3 : 1) > MAX_VECS) return FALSE; vec[v++] = *((struct iovec*)&pair->name); if (pair->value.length) { vec[v++] = IOV_EQUALS; vec[v++] = *((struct iovec*)&pair->value); } } str->buf = apr_pstrcatv(pool, vec, v, &str->length); return str->buf ? TRUE : FALSE; }
const char *create_large_request_message_body(apr_pool_t *pool) { struct iovec vecs[500]; const int num_vecs = 500; int i, j; apr_size_t len; for (i = 0; i < num_vecs; i++) { int chunk_len = 10 * (i + 1) * 3; char *chunk; char *buf; /* end with empty chunk */ if (i == num_vecs - 1) chunk_len = 0; buf = apr_pcalloc(pool, chunk_len + 1); for (j = 0; j < chunk_len; j += 10) memcpy(buf + j, "0123456789", 10); chunk = apr_pstrcat(pool, apr_psprintf(pool, "%x", chunk_len), CRLF, buf, CRLF, NULL); vecs[i].iov_base = chunk; vecs[i].iov_len = strlen(chunk); } return apr_pstrcatv(pool, vecs, num_vecs, &len); }
static const char* regen_key(apr_pool_t *p, apr_table_t *headers, apr_array_header_t *varray, const char *oldkey) { struct iovec *iov; int i, k; int nvec; const char *header; const char **elts; nvec = (varray->nelts * 2) + 1; iov = apr_palloc(p, sizeof(struct iovec) * nvec); elts = (const char **) varray->elts; /* TODO: * - Handle multiple-value headers better. (sort them?) * - Handle Case in-sensitive Values better. * This isn't the end of the world, since it just lowers the cache * hit rate, but it would be nice to fix. * * The majority are case insenstive if they are values (encoding etc). * Most of rfc2616 is case insensitive on header contents. * * So the better solution may be to identify headers which should be * treated case-sensitive? * HTTP URI's (3.2.3) [host and scheme are insensitive] * HTTP method (5.1.1) * HTTP-date values (3.3.1) * 3.7 Media Types [exerpt] * The type, subtype, and parameter attribute names are case- * insensitive. Parameter values might or might not be case-sensitive, * depending on the semantics of the parameter name. * 4.20 Except [exerpt] * Comparison of expectation values is case-insensitive for unquoted * tokens (including the 100-continue token), and is case-sensitive for * quoted-string expectation-extensions. */ for(i=0, k=0; i < varray->nelts; i++) { header = apr_table_get(headers, elts[i]); if (!header) { header = ""; } iov[k].iov_base = (char*) elts[i]; iov[k].iov_len = strlen(elts[i]); k++; iov[k].iov_base = (char*) header; iov[k].iov_len = strlen(header); k++; } iov[k].iov_base = (char*) oldkey; iov[k].iov_len = strlen(oldkey); k++; return apr_pstrcatv(p, iov, k, NULL); }
// helper function used for sending prepared data to socket for authorization against dovecot auth int send_auth_request(apr_pool_t * p, request_rec * r, int sock, const char *user, const char *pass, char *remotehost) { struct iovec concat[4]; size_t const up_size = strlen(user) + strlen(pass) + 2; if (up_size > BUFFMAX - 1024) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: User and pass length is over (or close) BUFFMAX=%i which is NOT allowed size=%u\n", BUFFMAX, (unsigned int)up_size); return 0; } size_t const eup_size = apr_base64_encode_len(up_size); char * const encoded_user_pass = (char *)apr_palloc(p, sizeof(char) * eup_size); ap_assert(encoded_user_pass != NULL); // this beautifull code snippet from bellow (concat blah blah) is needed for use of apr_pstrcatv // as without using apr_pstrcatv apr_pstrcat will remove \0 which we need for creating base64 encoded user_pass combination... concat[0].iov_base = (void *)"\0"; concat[0].iov_len = 1; concat[1].iov_base = (void *)user; concat[1].iov_len = strlen(user); concat[2].iov_base = (void *)"\0"; concat[2].iov_len = 1; concat[3].iov_base = (void *)pass; concat[3].iov_len = strlen(pass); char * const user_pass = apr_pstrcatv(p, concat, 4, NULL); ap_assert(user_pass != NULL); apr_base64_encode(encoded_user_pass, user_pass, up_size); char * const data = apr_psprintf(p, "AUTH\t1\tPLAIN\tservice=apache\tnologin" // local ip (lip) is hardcoded as we are using local unix socket anyway... "\tlip=127.0.0.1\trip=%s\tsecured\tresp=%s\n", remotehost, encoded_user_pass); ap_assert(data != NULL); size_t const d_size = strlen(data); if (send(sock, data, d_size, 0) > 0) { // scrub user credentials memset(user_pass, '\0', up_size); memset(encoded_user_pass, '\0', eup_size); memset(data, '\0', d_size); return 1; } else { return 0; } }
const char *create_large_response_message(apr_pool_t *pool) { const char *response = "HTTP/1.1 200 OK" CRLF "Transfer-Encoding: chunked" CRLF CRLF; struct iovec vecs[500]; const int num_vecs = 500; int i, j; apr_size_t len; vecs[0].iov_base = (char *)response; vecs[0].iov_len = strlen(response); for (i = 1; i < num_vecs; i++) { int chunk_len = 10 * i * 3; char *chunk; char *buf; /* end with empty chunk */ if (i == num_vecs - 1) chunk_len = 0; buf = apr_pcalloc(pool, chunk_len + 1); for (j = 0; j < chunk_len; j += 10) memcpy(buf + j, "0123456789", 10); chunk = apr_pstrcat(pool, apr_psprintf(pool, "%x", chunk_len), CRLF, buf, CRLF, NULL); vecs[i].iov_base = chunk; vecs[i].iov_len = strlen(chunk); } return apr_pstrcatv(pool, vecs, num_vecs, &len); }
static apr_status_t put_req(const char *c, const char *orig_path, parser_baton_t *ctx, apr_pool_t *pool) { apr_status_t status; apr_uri_t url; /* Build url */ #ifdef SERF_VERBOSE printf("Url discovered: %s\n", c); #endif status = apr_uri_parse(pool, c, &url); /* We got something that was minimally useful. */ if (status == 0 && url.path) { const char *path, *query, *fragment; /* This is likely a relative URL. So, merge and hope for the * best. */ if (!url.hostinfo && url.path[0] != '/') { struct iovec vec[2]; char *c; apr_size_t nbytes; c = strrchr(orig_path, '/'); /* assert c */ if (!c) { return APR_EGENERAL; } vec[0].iov_base = (char*)orig_path; vec[0].iov_len = c - orig_path + 1; /* If the HTML is cute and gives us ./foo - skip the ./ */ if (url.path[0] == '.' && url.path[1] == '/') { vec[1].iov_base = url.path + 2; vec[1].iov_len = strlen(url.path + 2); } else if (url.path[0] == '.' && url.path[1] == '.') { /* FIXME We could be cute and consolidate the path; we're a * toy example. So no. */ vec[1].iov_base = url.path; vec[1].iov_len = strlen(url.path); } else { vec[1].iov_base = url.path; vec[1].iov_len = strlen(url.path); } path = apr_pstrcatv(pool, vec, 2, &nbytes); } else { path = url.path; } query = url.query; fragment = url.fragment; return create_request(url.hostinfo, path, query, fragment, ctx, pool); } return APR_SUCCESS; }
int main(int argc, char const* argv[]) { apr_pool_t* pool = NULL; apr_pool_t* spool = NULL; int i; struct iovec cattext[101]; static char const SP = ' '; char const* outfile; apr_status_t status; apt_dir_layout_t* dirLayout = NULL; mrcp_client_t* client = NULL; mrcp_application_t* app = NULL; mrcp_session_t* sess = NULL; mpf_stream_capabilities_t* caps = NULL; mpf_termination_t* term = NULL; mrcp_channel_t* chan = NULL; struct stat info; if (argc < 2) { puts("Usage:"); printf("\t%s \"This is a synthetic voice.\"", argv[0]); exit(1); } /* Just detect various directory layout constellations */ if (stat(ROOT_DIR, &info)) ROOT_DIR = ROOT_DIR2; if (stat(ROOT_DIR, &info)) ROOT_DIR = ROOT_DIR3; /* Initialize platform first */ if (apr_initialize() != APR_SUCCESS) FAIL("Cannot initialize APR platform"); pool = apt_pool_create(); if (!pool) FAIL("Not enough memory"); for (i = 0; (i < argc - 2) && (i < 50); i += 2) { cattext[2 * i].iov_base = (void*) argv[i + 1]; cattext[2 * i].iov_len = strlen(argv[i + 1]); cattext[2 * i + 1].iov_base = (void*) &SP; cattext[2 * i + 1].iov_len = 1; } cattext[2 * i].iov_base = (void*) argv[i + 1]; cattext[2 * i].iov_len = strlen(argv[i + 1]); text = apr_pstrcatv(pool, cattext, 2 * i + 1, NULL); if (!text) FAIL("Not enough memory"); outfile = apr_pstrcat(pool, ROOT_DIR, "/data/", PCM_OUT_FILE, NULL); printf("This is a sample C UniMRCP client synthesizer scenario.\n"); printf("Use client configuration from %s/conf/unimrcpclient.xml\n", ROOT_DIR); printf("Use profile %s\n", MRCP_PROFILE); printf("Synthesize text: `%s'\n", text); printf("Write output to file: %s\n", outfile); printf("\n"); printf("Press enter to start the session...\n"); (void) getchar(); apt_log_instance_create(APT_LOG_OUTPUT_NONE, APT_PRIO_DEBUG, pool); apt_log_ext_handler_set(UniSynth_logger); dirLayout = apt_default_dir_layout_create(ROOT_DIR, pool); /* Create and start the client in a root dir */ client = unimrcp_client_create(dirLayout); if (!client) FAIL("Cannot create UniMRCP client"); app = mrcp_application_create(UniSynthAppMsgHandler, NULL, mrcp_client_memory_pool_get(client)); if (!app) FAIL("Cannot create MRCP application"); if (!mrcp_client_application_register(client, app, "Sample C app")) FAIL("Cannot register MRCP application"); if (!mrcp_client_start(client)) FAIL("Cannot start MRCP client"); /* Create a session using MRCP profile MRCP_PROFILE */ sess = mrcp_application_session_create(app, MRCP_PROFILE, NULL); if (!sess) FAIL("Cannot create session"); spool = mrcp_application_session_pool_get(sess); /* Create audio termination with capabilities */ caps = mpf_stream_capabilities_create(STREAM_DIRECTION_SEND, spool); if (!caps) FAIL("Error creating capabilities"); if (!mpf_codec_capabilities_add(&caps->codecs, MPF_SAMPLE_RATE_8000, "LPCM")) FAIL("Error adding codec capabilities"); term = mrcp_application_audio_termination_create(sess, &stream_vtable, caps, NULL); if (!term) FAIL("Cannot create audio termination"); /* Add signaling channel (and start processing in OnAdd method */ f = fopen(outfile, "wb"); if (!f) FAIL("Cannot open output file"); status = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool); if (status != APR_SUCCESS) FAIL("Cannot create mutex"); status = apr_thread_cond_create(&cond, pool); if (status != APR_SUCCESS) FAIL("Cannot create condition variable"); chan = mrcp_application_channel_create(sess, MRCP_SYNTHESIZER_RESOURCE, term, NULL, NULL); if (!chan) FAIL("Cannot create channel"); if (!mrcp_application_channel_add(sess, chan)) FAIL("Cannot add channel"); /* Now wait until the processing finishes */ apr_thread_mutex_lock(mutex); while (err < 0) apr_thread_cond_wait(cond, mutex); apr_thread_mutex_unlock(mutex); cleanup: if (sess) mrcp_application_session_terminate(sess); if (f) fclose(f); if (client) mrcp_client_shutdown(client); if (app) mrcp_application_destroy(app); if (client) mrcp_client_destroy(client); apt_log_instance_destroy(); if (pool) apr_pool_destroy(pool); apr_terminate(); puts("Program finished, memory released. Press any key to exit."); (void) getchar(); return err; }