void t02_several_add_methods(){ INIT_TEST(); onion_block *block=onion_block_new(); FAIL_IF_EQUAL(block, NULL); int i; for (i=0;i<1024;i++){ onion_block_add_char(block, (char)i); } onion_block_clear(block); onion_block_add_str(block, "first "); for (i=0;i<1024;i++) onion_block_add_str(block, "test "); FAIL_IF_NOT_STRSTR(onion_block_data(block), "test"); for (i=0;i<1024;i++) onion_block_add_data(block, "world", 4); FAIL_IF_STRSTR(onion_block_data(block), "world"); FAIL_IF_NOT_STRSTR(onion_block_data(block), "worl"); int s=onion_block_size(block); onion_block_add_block(block, block); FAIL_IF_NOT_EQUAL(onion_block_size(block), s+s); onion_block_free(block); END_TEST(); }
/** * @short Helps to prepare each pair. */ static void onion_dict_json_preorder(onion_block *block, const char *key, const void *value, int flags){ if (!onion_block_size(block)) // Error somewhere. return; char *s; s=onion_c_quote_new(key); if (s==NULL){ onion_block_clear(block); return; } onion_block_add_str(block, s); free(s); onion_block_add_char(block, ':'); if (flags&OD_DICT){ onion_block *tmp; tmp=onion_dict_to_json((onion_dict*)value); if (!tmp){ onion_block_clear(block); return; } onion_block_add_block(block, tmp); onion_block_free(tmp); } else{ s=onion_c_quote_new(value); if (s==NULL){ onion_block_clear(block); return; } onion_block_add_str(block, s); free(s); } onion_block_add_data(block, ", ",2); }
/** * @short Helps to prepare each pair. */ static void onion_dict_json_preorder(onion_block *block, const char *key, const void *value, int flags){ if (!onion_block_size(block)) // Error somewhere. return; onion_block_add_char(block,'\"'); onion_json_quote_add(block, key); onion_block_add_data(block,"\":",2); if (flags&OD_DICT){ onion_block *tmp; tmp=onion_dict_to_json((onion_dict*)value); if (!tmp){ onion_block_clear(block); return; } onion_block_add_block(block, tmp); onion_block_free(tmp); } else{ onion_block_add_char(block,'\"'); onion_json_quote_add(block, value); onion_block_add_char(block,'\"'); } onion_block_add_data(block, ", ",2); }
/** * @short Reads from the data to fulfill content-length data. */ static onion_connection_status parse_CONTENT_LENGTH(onion_request *req, onion_buffer *data){ onion_token *token=req->parser_data; int length=data->size-data->pos; int exit=0; if (length>=token->extra_size-token->pos){ exit=1; length=token->extra_size-token->pos; } onion_block_add_data(req->data, &data->data[data->pos], length); data->pos+=length; if (exit) return onion_request_process(req); return OCS_NEED_MORE_DATA; }
/** * @short Reads from the data to fulfill content-length data. */ static onion_connection_status parse_CONTENT_LENGTH(onion_request *req, onion_buffer *data){ ONION_DEBUG0("Adding data to request->data (non form POST)"); onion_token *token=req->parser_data; int length=data->size-data->pos; int exit=0; if (length>=token->extra_size-token->pos){ exit=1; length=token->extra_size-token->pos; } onion_block_add_data(req->data, &data->data[data->pos], length); data->pos+=length; if (exit) return OCS_REQUEST_READY; return OCS_NEED_MORE_DATA; }
/** * @short Adds some code to the top function */ void function_add_code(parser_status *st, const char *fmt, ...){ function_data *p=(function_data*)st->function_stack->tail->data; if (p->flags&F_NO_MORE_WRITE) return; char tmp[4096]; va_list ap; va_start(ap, fmt); vsnprintf(tmp, sizeof(tmp), fmt, ap); va_end(ap); if (use_orig_line_numbers){ char line[32]; int p=onion_block_size(st->current_code); if (p && onion_block_data(st->current_code)[p-1]!='\n') onion_block_add_char(st->current_code, '\n'); snprintf(line,sizeof(line),"#line %d\n", st->line); // I have to do it for every \n too. This is going to be slow. const char *orig=tmp; int lorig=strlen(orig); int i=0, li=0; for (i=0;i<lorig;i++){ if (orig[i]=='\n'){ onion_block_add_str(st->current_code, line); onion_block_add_data(st->current_code, &orig[li], i-li+1); li=i; } } if (i-1!=li){ onion_block_add_str(st->current_code, line); onion_block_add_str(st->current_code, &orig[li]); } } else{ //ONION_DEBUG("Add to level %d text %s",list_count(st->function_stack), tmp); onion_block_add_str(st->current_code, tmp); } }
/** * @short Reads from the data to fulfill content-length data. */ static onion_connection_status parse_CONTENT_LENGTH(onion_request *req, onion_buffer *data){ onion_token *token=req->parser_data; size_t skip=data->pos; // First packet will be headers + some data, later ony data int length=data->size-skip; bool exit=false; size_t current_size=onion_block_size(req->data); ONION_DEBUG0("Adding data to request->data (non form POST) %d + %d / %d [%d/%d] %p", current_size, length, token->extra_size, skip, data->size, data->data+current_size); if (length + current_size >= token->extra_size){ ONION_DEBUG0("Done"); exit=true; length=token->extra_size - current_size; } onion_block_add_data(req->data, &data->data[skip], length); data->pos+=length; // done if (exit) return OCS_REQUEST_READY; return OCS_NEED_MORE_DATA; }
onion_block *connect_and_send(const char *ip, const char *port, const onion_block * msg, size_t maxsize) { int fd; { struct addrinfo hints; struct addrinfo *server; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; if (getaddrinfo(ip, port, &hints, &server) < 0) { ONION_ERROR("Error getting server info"); return NULL; } fd = socket(server->ai_family, server->ai_socktype | SOCK_CLOEXEC, server->ai_protocol); if (connect(fd, server->ai_addr, server->ai_addrlen) == -1) { close(fd); fd = -1; ONION_ERROR("Error connecting to server %s:%s", ip, port); return NULL; } freeaddrinfo(server); } size_t left = onion_block_size(msg); const char *data = onion_block_data(msg); while (left > 0) { ONION_DEBUG("."); int towrite = (left > maxsize) ? maxsize : left; int ret = write(fd, data, towrite); FAIL_IF(ret <= 0); if (ret <= 0) { ONION_ERROR("Error sending data."); return NULL; } left -= ret; data += ret; } onion_block *bl = onion_block_new(); char tmp[256]; int r = 0; int total = 0; do { r = read(fd, tmp, sizeof(tmp)); ONION_DEBUG("+ %d", r); if (r > 0) { total += r; onion_block_add_data(bl, tmp, r); } } while (r > 0); ONION_DEBUG("Total %d", total); FAIL_IF(total == 0); close(fd); return bl; }
/** * @short Appends both blocks on the first. * @memberof onion_block_t */ int onion_block_add_block(onion_block *b, onion_block *toadd){ return onion_block_add_data(b, toadd->data, toadd->size); }
/** * @short Adds a string to the block * @memberof onion_block_t */ int onion_block_add_str(onion_block *b, const char *str){ int l=strlen(str)+1; onion_block_add_data(b, str, l); b->size--; return l; }