int timestamp_get_new(struct sdirs *sdirs, char *buf, size_t s, char *bufforfile, size_t bs, struct conf **cconfs) { time_t t=0; unsigned long index=0; struct bu *bu=NULL; struct bu *bu_list=NULL; const struct tm *ctm=NULL; // Want to prefix the timestamp with an index that increases by // one each time. This makes it far more obvious which backup depends // on which - even if the system clock moved around. Take that, // bacula! // This function orders the array with the highest index number last. if(bu_get_list(sdirs, &bu_list)) return -1; for(bu=bu_list; bu; bu=bu->next) if(!bu->next) index=bu->bno; bu_list_free(&bu_list); time(&t); ctm=localtime(&t); // Windows does not like the %T strftime format option - you get // complaints under gdb. index++; write_to_buf(buf, s, index, NULL, ctm); write_to_buf(bufforfile, bs, index, get_string(cconfs[OPT_TIMESTAMP_FORMAT]), ctm); return 0; }
int call_callback(struct fd_state *state, const char *path, char *sparams, char *scookies) { assert(state && path); struct callback_elem *elem = callback_head; while (elem) { if (strcmp(path, elem->path) == 0) { struct lh_response response; response.header[0] = 0; response.header_len = 0; response.body[0] = 0; response.body_len = 0; struct lh_kv_elem *params = parse_url_params(sparams); struct lh_kv_elem *cookies = parse_cookies(scookies); elem->callback(params, cookies, &response); free_kvs(params); free_kvs(cookies); write_response_header(state, "application/json", response.body_len, response.header); if (response.header_len > 0) write_to_buf(state, response.header, response.header_len); if (response.body_len > 0) write_to_buf(state, response.body, response.body_len); return 1; } elem = elem->next; } return 0; }
static void test_buffers_zlib_fin_at_chunk_end(void *arg) { char *msg = NULL; char *contents = NULL; char *expanded = NULL; buf_t *buf = NULL; tor_zlib_state_t *zlib_state = NULL; size_t out_len, in_len; size_t sz, headerjunk; (void) arg; buf = buf_new_with_capacity(128); /* will round up */ sz = buf_get_default_chunk_size(buf); msg = tor_malloc_zero(sz); write_to_buf(msg, 1, buf); tt_assert(buf->head); /* Fill up the chunk so the zlib stuff won't fit in one chunk. */ tt_uint_op(buf->head->memlen, OP_LT, sz); headerjunk = buf->head->memlen - 7; write_to_buf(msg, headerjunk-1, buf); tt_uint_op(buf->head->datalen, OP_EQ, headerjunk); tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk); /* Write an empty string, with finalization on. */ zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION); tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0); in_len = buf_datalen(buf); contents = tor_malloc(in_len); tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0); tt_uint_op(in_len, OP_GT, headerjunk); tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len, contents + headerjunk, in_len - headerjunk, ZLIB_METHOD, 1, LOG_WARN)); tt_int_op(out_len, OP_EQ, 0); tt_assert(expanded); done: buf_free(buf); tor_zlib_free(zlib_state); tor_free(contents); tor_free(expanded); tor_free(msg); }
/* Simple connection_write_to_buf_impl_ replacement that unconditionally * writes to outbuf. */ static void connection_write_to_buf_impl_replacement(const char *string, size_t len, connection_t *conn, int zlib) { (void) zlib; tor_assert(string); tor_assert(conn); write_to_buf(string, len, conn->outbuf); }
void connection_write_to_buf_mock(const char *string, size_t len, connection_t *conn, int zlib) { (void) zlib; tor_assert(string); tor_assert(conn); write_to_buf(string, len, conn->outbuf); }
static int write_response_header(struct fd_state *state, const char* mime, int body_len, const char* user_header) { assert(state && user_header && mime); char buf[HEADER_BUF_SIZE] = {0}; const char* fmt = "HTTP/1.1 200 OK\r\n" \ "Content-Type: %s\r\n" \ "Content-Length: %u\r\n" \ "%s\r\n"; snprintf(buf, sizeof(buf), fmt, mime, body_len, user_header); write_to_buf(state, buf, strlen(buf)); return 0; }
// terminate all profiling by critical error // TODO: don't send data to host static void terminate_error(char *errstr, int send_to_host) { LOGE("termination all with err '%s'\n", errstr); struct msg_data_t *msg = NULL; if (send_to_host != 0) { msg = gen_message_error(errstr); if (msg) { if (write_to_buf(msg) != 0) LOGE("write to buf fail\n"); free_msg_data(msg); } else { LOGI("cannot generate error message\n"); } } terminate_all(); }
static inline void set_line_prev_idx(unsigned int line_idx) { int i = 0; char *c; c = (char*)&line_idx; for (i = 0; i < sizeof(unsigned int); i++ ) { write_to_buf(*c); c++; } return; }
static unsigned int cp_to_buffer(char* buf) { char *p_string = buf; unsigned int next_line_idx_idx; while (*p_string != '\0') { write_to_buf(*p_string); if (*p_string == '\n' ) { set_line_prev_idx(dsp_ctx.buffer.tail_line); dsp_ctx.buffer.lastchar = get_buf_idx(dsp_ctx.buffer.lastchar + sizeof(unsigned int)); next_line_idx_idx = get_buf_idx(dsp_ctx.buffer.tail_line - sizeof(unsigned int)); set_line_next_idx(next_line_idx_idx, dsp_ctx.buffer.lastchar); dsp_ctx.buffer.tail_line = dsp_ctx.buffer.lastchar; p_string++; break; } p_string++; } return (unsigned int)((unsigned long)p_string - (unsigned long)buf); }
static void test_buffer_ext_or_cmd(void *arg) { ext_or_cmd_t *cmd = NULL; buf_t *buf = buf_new(); char *tmp = NULL; (void) arg; /* Empty -- should give "not there. */ tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_EQ, cmd); /* Three bytes: shouldn't work. */ write_to_buf("\x00\x20\x00", 3, buf); tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_EQ, cmd); tt_int_op(3, OP_EQ, buf_datalen(buf)); /* 0020 0000: That's a nil command. It should work. */ write_to_buf("\x00", 1, buf); tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_NE, cmd); tt_int_op(0x20, OP_EQ, cmd->cmd); tt_int_op(0, OP_EQ, cmd->len); tt_int_op(0, OP_EQ, buf_datalen(buf)); ext_or_cmd_free(cmd); cmd = NULL; /* Now try a length-6 command with one byte missing. */ write_to_buf("\x10\x21\x00\x06""abcde", 9, buf); tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_EQ, cmd); write_to_buf("f", 1, buf); tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_NE, cmd); tt_int_op(0x1021, OP_EQ, cmd->cmd); tt_int_op(6, OP_EQ, cmd->len); tt_mem_op("abcdef", OP_EQ, cmd->body, 6); tt_int_op(0, OP_EQ, buf_datalen(buf)); ext_or_cmd_free(cmd); cmd = NULL; /* Now try a length-10 command with 4 extra bytes. */ write_to_buf("\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18, buf); tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_NE, cmd); tt_int_op(0xffff, OP_EQ, cmd->cmd); tt_int_op(10, OP_EQ, cmd->len); tt_mem_op("loremipsum", OP_EQ, cmd->body, 10); tt_int_op(4, OP_EQ, buf_datalen(buf)); ext_or_cmd_free(cmd); cmd = NULL; /* Finally, let's try a maximum-length command. We already have the header * waiting. */ tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tmp = tor_malloc_zero(65535); write_to_buf(tmp, 65535, buf); tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd)); tt_ptr_op(NULL, OP_NE, cmd); tt_int_op(0x1000, OP_EQ, cmd->cmd); tt_int_op(0xffff, OP_EQ, cmd->len); tt_mem_op(tmp, OP_EQ, cmd->body, 65535); tt_int_op(0, OP_EQ, buf_datalen(buf)); ext_or_cmd_free(cmd); cmd = NULL; done: ext_or_cmd_free(cmd); buf_free(buf); tor_free(tmp); }
void do_proxy(int clifd, const struct sockaddr_in *cliaddr, int pid) { /* get the request from the client */ char *request; int request_len; request = calloc(MAXLINE, sizeof(char)); request_len = Read(clifd, request, MAXLINE); /* get the request line, header lines and entity body */ const char *request_line, *header_lines, *body; int rlen, hlen, blen; separate_http_message(request, request_len, &request_line, &rlen, &header_lines, &hlen, &body, &blen); /* get header fields */ struct header_field *header_fields; header_fields = get_header_fields(header_lines, hlen); /* remove Connection and Proxy-Connection from header fields */ remove_header_field(&header_fields, "Connection"); remove_header_field(&header_fields, "Proxy-Connection"); /* get the hostname of the server */ const struct header_field *host_header_field; char *host; const char *p_host, *method, *url, *version; int hostlen, methodlen, urllen, versionlen; if ((host_header_field = get_header_field(header_fields, "Host")) == NULL) { get_start_fields(request_line, rlen, &method, &methodlen, &url, &urllen, &version, &versionlen); get_host_from_url(url, &p_host, &hostlen); } else { p_host = host_header_field->value; hostlen = host_header_field->vlen; } host = calloc(1, hostlen + 1); memcpy(host, p_host, hostlen); /* connect to the server */ int servfd; struct sockaddr_in servaddr; socklen_t servaddrlen; struct addrinfo hints, *result; fprintf(stdout, "---pid=%d, Connect to the server\n", pid); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; getaddrinfo(host, "http", &hints, &result); memcpy(&servaddr, result->ai_addr, sizeof(servaddr)); servaddrlen = result->ai_addrlen; freeaddrinfo(result); servfd = Socket(AF_INET, SOCK_STREAM, 0); Connect(servfd, (struct sockaddr *)&servaddr, servaddrlen); /* assemble the new request, assuming that the whole request is less than 4096 bytes */ char *new_request, *bufpos; int new_request_len; struct header_field *iter_header_field; new_request = calloc(MAXLINE, sizeof(char)); new_request_len = 0; bufpos = new_request; bufpos = write_to_buf(bufpos, request_line, rlen); bufpos = write_to_buf(bufpos, "\r\n", 2); new_request_len += rlen + 2; for (iter_header_field = header_fields; iter_header_field; iter_header_field = iter_header_field->next) { bufpos = write_to_buf(bufpos, iter_header_field->name, iter_header_field->nlen); bufpos = write_to_buf(bufpos, ": ", 2); bufpos = write_to_buf(bufpos, iter_header_field->value, iter_header_field->vlen); bufpos = write_to_buf(bufpos, "\r\n", 2); new_request_len += iter_header_field->nlen + iter_header_field->vlen + 4; } bufpos = write_to_buf(bufpos, "\r\n", 2); bufpos = write_to_buf(bufpos, body, blen); new_request_len += blen + 2; /* send the new request to the server */ fprintf(stdout, "---pid=%d, Send the new request to the server\n", pid); Write(servfd, new_request, new_request_len); /* get and send back the response */ char *response; int response_len; fprintf(stdout, "---pid=%d, Send the response back to the client\n", pid); response = calloc(MAXLINE, sizeof(char)); while ((response_len = Read(servfd, response, MAXLINE)) > 0) { fprintf(stdout, "---pid=%d, %d bytes received from the server\n", pid, response_len); Write(clifd, response, response_len); } /* close the server socket */ fprintf(stdout, "---pid=%d, Close the server socket\n", pid); close(servfd); /* release memory */ struct header_field *next_header_field; free(request); free(new_request); free(response); free(host); for (iter_header_field = header_fields; iter_header_field; iter_header_field = next_header_field) { next_header_field = iter_header_field->next; free(iter_header_field); } }
static void test_buffer_allocation_tracking(void *arg) { char *junk = tor_malloc(16384); buf_t *buf1 = NULL, *buf2 = NULL; int i; (void)arg; crypto_rand(junk, 16384); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); buf1 = buf_new(); tt_assert(buf1); buf2 = buf_new(); tt_assert(buf2); tt_int_op(buf_allocation(buf1), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); fetch_from_buf(junk, 100, buf1); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */ tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really freed. */ write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */ /* * We bounce back up to 16384 by allocating a new chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 5*4096); /* that chunk was new. */ /* Make a really huge buffer */ for (i = 0; i < 1000; ++i) { write_to_buf(junk, 4000, buf2); } tt_int_op(buf_allocation(buf2), OP_GE, 4008000); tt_int_op(buf_get_total_allocation(), OP_GE, 4008000); buf_free(buf2); buf2 = NULL; tt_int_op(buf_get_total_allocation(), OP_LT, 4008000); tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1)); buf_free(buf1); buf1 = NULL; tt_int_op(buf_get_total_allocation(), OP_EQ, 0); done: buf_free(buf1); buf_free(buf2); tor_free(junk); }
static void test_buffer_time_tracking(void *arg) { buf_t *buf=NULL, *buf2=NULL; struct timeval tv0; const time_t START = 1389288246; const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000); int i; char tmp[4096]; (void)arg; crypto_rand(tmp, sizeof(tmp)); tv0.tv_sec = START; tv0.tv_usec = 0; buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ tt_assert(buf); /* Empty buffer means the timestamp is 0. */ tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC)); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); tor_gettimeofday_cache_set(&tv0); write_to_buf("ABCDEFG", 7, buf); tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); buf2 = buf_copy(buf); tt_assert(buf2); tt_int_op(1234, OP_EQ, buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234)); /* Now add more bytes; enough to overflow the first chunk. */ tv0.tv_usec += 123 * 1000; tor_gettimeofday_cache_set(&tv0); for (i = 0; i < 600; ++i) write_to_buf("ABCDEFG", 7, buf); tt_int_op(4207, OP_EQ, buf_datalen(buf)); /* The oldest bytes are still in the front. */ tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); /* Once those bytes are dropped, the chunk is still on the first * timestamp. */ fetch_from_buf(tmp, 100, buf); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); /* But once we discard the whole first chunk, we get the data in the second * chunk. */ fetch_from_buf(tmp, 4000, buf); tt_int_op(107, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); /* This time we'll be grabbing a chunk from the freelist, and making sure its time gets updated */ tv0.tv_sec += 5; tv0.tv_usec = 617*1000; tor_gettimeofday_cache_set(&tv0); for (i = 0; i < 600; ++i) write_to_buf("ABCDEFG", 7, buf); tt_int_op(4307, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); fetch_from_buf(tmp, 4000, buf); fetch_from_buf(tmp, 306, buf); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617)); tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000)); done: buf_free(buf); buf_free(buf2); }
static void test_buffer_pullup(void *arg) { buf_t *buf; char *stuff, *tmp; const char *cp; size_t sz; (void)arg; stuff = tor_malloc(16384); tmp = tor_malloc(16384); buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ tt_assert(buf); tt_int_op(buf_get_default_chunk_size(buf), OP_EQ, 4096); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* There are a bunch of cases for pullup. One is the trivial case. Let's mess around with an empty buffer. */ buf_pullup(buf, 16); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_EQ, NULL); tt_uint_op(sz, OP_EQ, 0); /* Let's make sure nothing got allocated */ tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* Case 1: everything puts into the first chunk with some moving. */ /* Let's add some data. */ crypto_rand(stuff, 16384); write_to_buf(stuff, 3000, buf); write_to_buf(stuff+3000, 3000, buf); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_LE, 4096); /* Make room for 3000 bytes in the first chunk, so that the pullup-move code * can get tested. */ tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000); tt_mem_op(tmp,OP_EQ, stuff, 3000); buf_pullup(buf, 2048); assert_buf_ok(buf); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_GE, 2048); tt_mem_op(cp,OP_EQ, stuff+3000, 2048); tt_int_op(3000, OP_EQ, buf_datalen(buf)); tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 0); tt_mem_op(tmp,OP_EQ, stuff+3000, 2048); buf_free(buf); /* Now try the large-chunk case. */ buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ write_to_buf(stuff, 4000, buf); write_to_buf(stuff+4000, 4000, buf); write_to_buf(stuff+8000, 4000, buf); write_to_buf(stuff+12000, 4000, buf); tt_int_op(buf_datalen(buf), OP_EQ, 16000); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_LE, 4096); buf_pullup(buf, 12500); assert_buf_ok(buf); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_GE, 12500); tt_mem_op(cp,OP_EQ, stuff, 12500); tt_int_op(buf_datalen(buf), OP_EQ, 16000); fetch_from_buf(tmp, 12400, buf); tt_mem_op(tmp,OP_EQ, stuff, 12400); tt_int_op(buf_datalen(buf), OP_EQ, 3600); fetch_from_buf(tmp, 3500, buf); tt_mem_op(tmp,OP_EQ, stuff+12400, 3500); fetch_from_buf(tmp, 100, buf); tt_mem_op(tmp,OP_EQ, stuff+15900, 10); buf_free(buf); /* Make sure that the pull-up-whole-buffer case works */ buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ write_to_buf(stuff, 4000, buf); write_to_buf(stuff+4000, 4000, buf); fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */ buf_pullup(buf, 16000); /* Way too much. */ assert_buf_ok(buf); buf_get_first_chunk_data(buf, &cp, &sz); tt_ptr_op(cp, OP_NE, NULL); tt_int_op(sz, OP_EQ, 7900); tt_mem_op(cp,OP_EQ, stuff+100, 7900); buf_free(buf); buf = NULL; tt_int_op(buf_get_total_allocation(), OP_EQ, 0); done: buf_free(buf); tor_free(stuff); tor_free(tmp); }
/** Run unit tests for buffers.c */ static void test_buffers_basic(void *arg) { char str[256]; char str2[256]; buf_t *buf = NULL, *buf2 = NULL; const char *cp; int j; size_t r; (void) arg; /**** * buf_new ****/ if (!(buf = buf_new())) TT_DIE(("Assertion failed.")); //test_eq(buf_capacity(buf), 4096); tt_int_op(buf_datalen(buf),OP_EQ, 0); /**** * General pointer frobbing */ for (j=0;j<256;++j) { str[j] = (char)j; } write_to_buf(str, 256, buf); write_to_buf(str, 256, buf); tt_int_op(buf_datalen(buf),OP_EQ, 512); fetch_from_buf(str2, 200, buf); tt_mem_op(str,OP_EQ, str2, 200); tt_int_op(buf_datalen(buf),OP_EQ, 312); memset(str2, 0, sizeof(str2)); fetch_from_buf(str2, 256, buf); tt_mem_op(str+200,OP_EQ, str2, 56); tt_mem_op(str,OP_EQ, str2+56, 200); tt_int_op(buf_datalen(buf),OP_EQ, 56); memset(str2, 0, sizeof(str2)); /* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add * another 3584 bytes, we hit the end. */ for (j=0;j<15;++j) { write_to_buf(str, 256, buf); } assert_buf_ok(buf); tt_int_op(buf_datalen(buf),OP_EQ, 3896); fetch_from_buf(str2, 56, buf); tt_int_op(buf_datalen(buf),OP_EQ, 3840); tt_mem_op(str+200,OP_EQ, str2, 56); for (j=0;j<15;++j) { memset(str2, 0, sizeof(str2)); fetch_from_buf(str2, 256, buf); tt_mem_op(str,OP_EQ, str2, 256); } tt_int_op(buf_datalen(buf),OP_EQ, 0); buf_free(buf); buf = NULL; /* Okay, now make sure growing can work. */ buf = buf_new_with_capacity(16); //test_eq(buf_capacity(buf), 16); write_to_buf(str+1, 255, buf); //test_eq(buf_capacity(buf), 256); fetch_from_buf(str2, 254, buf); tt_mem_op(str+1,OP_EQ, str2, 254); //test_eq(buf_capacity(buf), 256); assert_buf_ok(buf); write_to_buf(str, 32, buf); //test_eq(buf_capacity(buf), 256); assert_buf_ok(buf); write_to_buf(str, 256, buf); assert_buf_ok(buf); //test_eq(buf_capacity(buf), 512); tt_int_op(buf_datalen(buf),OP_EQ, 33+256); fetch_from_buf(str2, 33, buf); tt_int_op(*str2,OP_EQ, str[255]); tt_mem_op(str2+1,OP_EQ, str, 32); //test_eq(buf_capacity(buf), 512); tt_int_op(buf_datalen(buf),OP_EQ, 256); fetch_from_buf(str2, 256, buf); tt_mem_op(str,OP_EQ, str2, 256); /* now try shrinking: case 1. */ buf_free(buf); buf = buf_new_with_capacity(33668); for (j=0;j<67;++j) { write_to_buf(str,255, buf); } //test_eq(buf_capacity(buf), 33668); tt_int_op(buf_datalen(buf),OP_EQ, 17085); for (j=0; j < 40; ++j) { fetch_from_buf(str2, 255,buf); tt_mem_op(str2,OP_EQ, str, 255); } /* now try shrinking: case 2. */ buf_free(buf); buf = buf_new_with_capacity(33668); for (j=0;j<67;++j) { write_to_buf(str,255, buf); } for (j=0; j < 20; ++j) { fetch_from_buf(str2, 255,buf); tt_mem_op(str2,OP_EQ, str, 255); } for (j=0;j<80;++j) { write_to_buf(str,255, buf); } //test_eq(buf_capacity(buf),33668); for (j=0; j < 120; ++j) { fetch_from_buf(str2, 255,buf); tt_mem_op(str2,OP_EQ, str, 255); } /* Move from buf to buf. */ buf_free(buf); buf = buf_new_with_capacity(4096); buf2 = buf_new_with_capacity(4096); for (j=0;j<100;++j) write_to_buf(str, 255, buf); tt_int_op(buf_datalen(buf),OP_EQ, 25500); for (j=0;j<100;++j) { r = 10; move_buf_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 0); } tt_int_op(buf_datalen(buf),OP_EQ, 24500); tt_int_op(buf_datalen(buf2),OP_EQ, 1000); for (j=0;j<3;++j) { fetch_from_buf(str2, 255, buf2); tt_mem_op(str2,OP_EQ, str, 255); } r = 8192; /*big move*/ move_buf_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 0); r = 30000; /* incomplete move */ move_buf_to_buf(buf2, buf, &r); tt_int_op(r,OP_EQ, 13692); for (j=0;j<97;++j) { fetch_from_buf(str2, 255, buf2); tt_mem_op(str2,OP_EQ, str, 255); } buf_free(buf); buf_free(buf2); buf = buf2 = NULL; buf = buf_new_with_capacity(5); cp = "Testing. This is a moderately long Testing string."; for (j = 0; cp[j]; j++) write_to_buf(cp+j, 1, buf); tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7)); tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6)); tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3)); tt_int_op(39,OP_EQ, buf_find_string_offset(buf, "ing str", 7)); tt_int_op(35,OP_EQ, buf_find_string_offset(buf, "Testing str", 11)); tt_int_op(32,OP_EQ, buf_find_string_offset(buf, "ng ", 3)); tt_int_op(43,OP_EQ, buf_find_string_offset(buf, "string.", 7)); tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "shrdlu", 6)); tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "Testing thing", 13)); tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "ngx", 3)); buf_free(buf); buf = NULL; /* Try adding a string too long for any freelist. */ { char *cp = tor_malloc_zero(65536); buf = buf_new(); write_to_buf(cp, 65536, buf); tor_free(cp); tt_int_op(buf_datalen(buf), OP_EQ, 65536); buf_free(buf); buf = NULL; } done: if (buf) buf_free(buf); if (buf2) buf_free(buf2); }
static void write_response_error(struct fd_state *state) { const char* msg = "HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n"; write_to_buf(state, msg, strlen(msg)); }
static void test_buffer_allocation_tracking(void *arg) { char *junk = tor_malloc(16384); buf_t *buf1 = NULL, *buf2 = NULL; int i; (void)arg; crypto_rand(junk, 16384); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); buf1 = buf_new(); tt_assert(buf1); buf2 = buf_new(); tt_assert(buf2); tt_int_op(buf_allocation(buf1), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); write_to_buf(junk, 4000, buf1); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); fetch_from_buf(junk, 100, buf1); tt_int_op(buf_allocation(buf1), OP_EQ, 16384); /* still 4 4k chunks */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); fetch_from_buf(junk, 4096, buf1); /* drop a 1k chunk... */ tt_int_op(buf_allocation(buf1), OP_EQ, 3*4096); /* now 3 4k chunks */ #ifdef ENABLE_BUF_FREELISTS tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); /* that chunk went onto the freelist. */ #else tt_int_op(buf_get_total_allocation(), OP_EQ, 12288); /* that chunk was really freed. */ #endif write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), OP_EQ, 4096); /* another 4k chunk. */ /* * If we're using freelists, size stays at 16384 because we just pulled a * chunk from the freelist. If we aren't, we bounce back up to 16384 by * allocating a new chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 16384); write_to_buf(junk, 4000, buf2); tt_int_op(buf_allocation(buf2), OP_EQ, 8192); /* another 4k chunk. */ tt_int_op(buf_get_total_allocation(), OP_EQ, 5*4096); /* that chunk was new. */ /* Make a really huge buffer */ for (i = 0; i < 1000; ++i) { write_to_buf(junk, 4000, buf2); } tt_int_op(buf_allocation(buf2), OP_GE, 4008000); tt_int_op(buf_get_total_allocation(), OP_GE, 4008000); buf_free(buf2); buf2 = NULL; tt_int_op(buf_get_total_allocation(), OP_LT, 4008000); buf_shrink_freelists(1); tt_int_op(buf_get_total_allocation(), OP_EQ, buf_allocation(buf1)); buf_free(buf1); buf1 = NULL; buf_shrink_freelists(1); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); done: buf_free(buf1); buf_free(buf2); buf_shrink_freelists(1); tor_free(junk); }
static void test_buffer_copy(void *arg) { buf_t *buf=NULL, *buf2=NULL; const char *s; size_t len; char b[256]; int i; (void)arg; buf = buf_new(); tt_assert(buf); /* Copy an empty buffer. */ tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_assert(buf2); tt_int_op(0, OP_EQ, buf_datalen(buf2)); /* Now try with a short buffer. */ s = "And now comes an act of enormous enormance!"; len = strlen(s); write_to_buf(s, len, buf); tt_int_op(len, OP_EQ, buf_datalen(buf)); /* Add junk to buf2 so we can test replacing.*/ write_to_buf("BLARG", 5, buf2); tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(len, OP_EQ, buf_datalen(buf2)); fetch_from_buf(b, len, buf2); tt_mem_op(b, OP_EQ, s, len); /* Now free buf2 and retry so we can test allocating */ buf_free(buf2); buf2 = NULL; tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(len, OP_EQ, buf_datalen(buf2)); fetch_from_buf(b, len, buf2); tt_mem_op(b, OP_EQ, s, len); /* Clear buf for next test */ fetch_from_buf(b, len, buf); tt_int_op(buf_datalen(buf),OP_EQ,0); /* Okay, now let's try a bigger buffer. */ s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit " "esse quam nihil molestiae consequatur, vel illum qui dolorem eum " "fugiat quo voluptas nulla pariatur?"; len = strlen(s); for (i = 0; i < 256; ++i) { b[0]=i; write_to_buf(b, 1, buf); write_to_buf(s, len, buf); } tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf)); tt_int_op(buf_datalen(buf2), OP_EQ, buf_datalen(buf)); for (i = 0; i < 256; ++i) { fetch_from_buf(b, len+1, buf2); tt_int_op((unsigned char)b[0],OP_EQ,i); tt_mem_op(b+1, OP_EQ, s, len); } done: if (buf) buf_free(buf); if (buf2) buf_free(buf2); }