static int tunnel_in_connect(Tunnel *tunnel) { Http_response *response; int n; if(tunnel->in_fd!=INVALID_SOCKET)return -1; tunnel->in_fd=do_connect(&tunnel->address); if(tunnel->in_fd==INVALID_SOCKET)return -1; //发送get请求; if(http_get(tunnel->in_fd,&tunnel->dest)==-1)return -1; //解析接收到的响应; n=http_parse_response(tunnel->in_fd,&response); if(n<=0); else if(response->major_version!=1||(response->minor_version!=1&&response->minor_version!=0))//不是1.1或者1.0 { n=-1; } else if(response->status_code!=200) { n=-1; } if(response!=NULL)http_destroy_response(response); /* if(n>0) { //tunnel->in_total_raw+=n; } else */ if ( n <= 0 ) return n; return 1; }
int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; log_init("client.log", 1); char buffer[2049]; int buflen; char url[256], host[256], res[256]; printf("URL to access: "); gets(url); if(strncmp(url, "http://", 7)) { printf("error: url should started with http://\n"); return -1; } int i, len = strlen(url), hostlen = 0; for(i = 7; i < len; i++, hostlen++) { if(url[i] == ':') { strncpy(host, url + 7, hostlen); portno = atoi(url + i + 1); while(i < len && url[i] != '/') i++; if(i >= len) strcpy(res, "/"); else strcpy(res, url + i); break; } else if(url[i] == '/') { strncpy(host, url + 7, hostlen); portno = 80; strcpy(res, url + i); break; } } if(i >= len) { printf("error: malformed url"); return 0; } printf("connecting to host %s at port %d with url %s\n", host, portno, res); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) perror("error while opening socket: "); server = gethostbyname(host); if (server == NULL) { perror("host not found: "); return 0; } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { perror("error while connecting: "); return 0; } http_request_t req; http_response_t resp; http_request_init(&req); http_response_init(&resp); req.type = HTTP_GET; strcpy(req.url, res); req.version = HTTP_VERSION_1_1; sprintf(host, "%s:%d", host, portno); dict_put(req.fields, "Host", host); if(0 > http_assemble_request(&req, sockfd)) { perror("error while writing: "); return 0; } buflen = 0; do { n = read(sockfd, buffer + buflen, 2048 - buflen); if(n > 0) buflen += n; } while(n > 0 && buflen < 2048); puts("===raw resp==="); for(i = 0; i < buflen; i++) { putchar(buffer[i]); } puts("\n===end===\n"); if(http_parse_response(&resp, buffer, buflen)) { printf("error while parsing response\n"); return 0; } printf("%s\n", resp.document); http_request_free(&req); http_response_free(&resp); close(sockfd); log_close(); return 0; }
static void on_read(void *arg) { module_data_t *mod = arg; asc_timer_destroy(mod->timeout_timer); mod->timeout_timer = NULL; char *buffer = mod->buffer; int skip = mod->ts_len_in_buf; int r = asc_socket_recv(mod->sock, buffer + skip, HTTP_BUFFER_SIZE - skip); if(r <= 0) { on_close(mod); return; } r += mod->ts_len_in_buf;// Imagine that we've received more (+ previous part) int response = 0; parse_match_t m[4]; // parse response if(mod->ready_state == 0) { if(!http_parse_response(buffer, m)) { call_error(mod, "invalid response"); on_close(mod); return; } lua_newtable(lua); response = lua_gettop(lua); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_pushvalue(lua, -2); // duplicate table lua_setfield(lua, -2, __response); lua_pop(lua, 1); // options lua_pushnumber(lua, atoi(&buffer[m[2].so])); lua_setfield(lua, response, __code); lua_pushlstring(lua, &buffer[m[3].so], m[3].eo - m[3].so); lua_setfield(lua, response, __message); skip = m[0].eo; mod->ready_state = 1; if(skip >= r) { lua_pop(lua, 1); // response return; } } // parse headers if(mod->ready_state == 1) { if(!response) { lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_getfield(lua, -1, __response); lua_remove(lua, -2); response = lua_gettop(lua); } int headers_count = 0; lua_getfield(lua, response, __headers); if(lua_isnil(lua, -1)) { lua_pop(lua, 1); lua_newtable(lua); lua_pushvalue(lua, -1); lua_setfield(lua, response, __headers); } else { headers_count = luaL_len(lua, -1); } const int headers = lua_gettop(lua); while(skip < r && http_parse_header(&buffer[skip], m)) { const size_t so = m[1].so; const size_t length = m[1].eo - so; if(!length) { skip += m[0].eo; mod->ready_state = 2; break; } const char *header = &buffer[skip + so]; if(!strncasecmp(header, __transfer_encoding, sizeof(__transfer_encoding) - 1)) { const char *val = &header[sizeof(__transfer_encoding) - 1]; if(!strncasecmp(val, __chunked, sizeof(__chunked) - 1)) mod->is_chunked = 1; } else if(!strncasecmp(header, __connection, sizeof(__connection) - 1)) { const char *val = &header[sizeof(__connection) - 1]; if(!strncasecmp(val, __close, sizeof(__close) - 1)) mod->is_close = 1; else if(!strncasecmp(val, __keep_alive, sizeof(__keep_alive) - 1)) mod->is_keep_alive = 1; } else if(!strncasecmp(header, __content_length, sizeof(__content_length) - 1)) { const char *val = &header[sizeof(__content_length) - 1]; mod->is_content_length = 1; mod->chunk_left = strtoul(val, NULL, 10); } ++headers_count; lua_pushnumber(lua, headers_count); lua_pushlstring(lua, header, length); lua_settable(lua, headers); skip += m[0].eo; } lua_pop(lua, 1); // headers if(mod->ready_state == 2) { get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushvalue(lua, response); lua_call(lua, 2, 0); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref); lua_pushnil(lua); lua_setfield(lua, -2, __response); lua_pop(lua, 1); // options } lua_pop(lua, 1); // response if(skip >= r) return; } // content if(mod->ready_state == 2) { /* Push to stream */ if (mod->is_ts) { int pos = skip - mod->ts_len_in_buf;// buffer rewind while (r - pos >= TS_PACKET_SIZE) { module_stream_send(mod, (uint8_t*)&mod->buffer[pos]); pos += TS_PACKET_SIZE; } int left = r - pos; if (left > 0) {//there is something usefull in the end of buffer, move it to begin if (pos > 0) memmove(&mod->buffer[0], &mod->buffer[pos], left); mod->ts_len_in_buf = left; } else {//all data is processed mod->ts_len_in_buf = 0; } } // Transfer-Encoding: chunked else if(mod->is_chunked) { while(skip < r) { if(!mod->chunk_left) { if(!http_parse_chunk(&buffer[skip], m)) { call_error(mod, "invalid chunk"); on_close(mod); return; } char cs_str[] = "00000000"; const size_t cs_size = m[1].eo - m[1].so; const size_t cs_skip = 8 - cs_size; memcpy(&cs_str[cs_skip], &buffer[skip], cs_size); uint8_t cs_hex[4]; str_to_hex(cs_str, cs_hex, sizeof(cs_hex)); mod->chunk_left = (cs_hex[0] << 24) | (cs_hex[1] << 16) | (cs_hex[2] << 8) | (cs_hex[3] ); skip += m[0].eo; if(!mod->chunk_left) { if(mod->is_keep_alive) { // keep-alive connection get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushstring(lua, ""); lua_call(lua, 2, 0); } else { // close connection on_close(mod); } return; } } const size_t r_skip = r - skip; get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); if(mod->chunk_left < r_skip) { lua_pushlstring(lua, &buffer[skip], mod->chunk_left); lua_call(lua, 2, 0); skip += mod->chunk_left; mod->chunk_left = 0; if(buffer[skip] == '\r') ++skip; if(buffer[skip] == '\n') ++skip; else { call_error(mod, "invalid chunk"); on_close(mod); return; } } else { lua_pushlstring(lua, &buffer[skip], r_skip); lua_call(lua, 2, 0); mod->chunk_left -= r_skip; break; } } } // Content-Length else if(mod->is_content_length) { if(mod->chunk_left > 0) { const size_t r_skip = r - skip; get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); if(mod->chunk_left > r_skip) { lua_pushlstring(lua, &buffer[skip], r_skip); lua_call(lua, 2, 0); mod->chunk_left -= r_skip; } else { lua_pushlstring(lua, &buffer[skip], mod->chunk_left); lua_call(lua, 2, 0); mod->chunk_left = 0; if(mod->is_keep_alive) { // keep-alive connection get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushstring(lua, ""); lua_call(lua, 2, 0); } else { // close connection on_close(mod); } return; } } } // Stream else { get_lua_callback(mod); lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self); lua_pushlstring(lua, &buffer[skip], r - skip); lua_call(lua, 2, 0); } } } /* on_read */
/* Extract http_pair_t objects from flow's packet_t chain */ int flow_extract_http(flow_t *f) { /* check if the flow is carrying HTTP again */ if( f->http == FALSE) return 1; /* * Find the actual FIN sequences. */ seq_t *seq = f->order->src; seq_t *src_fin_seq = NULL; seq_t *dst_fin_seq = NULL; int found = 0; while(seq != NULL) { /* Update flow's first byte time. * FBT of flow refers to the payload's FBT. */ if(seq->pkt != NULL && found == 0) { found = 1; f->fb_sec = seq->cap_sec; f->fb_usec = seq->cap_usec; } /*Search the FIN sequence in sequence queue.*/ if(seq->th_flags & TH_FIN == TH_FIN) { src_fin_seq = seq; break; } seq = seq->next; } seq = f->order->dst; while(seq != NULL) { /*Search the FIN sequence in sequence queue.*/ if(seq->th_flags & TH_FIN == TH_FIN) { dst_fin_seq = seq; break; } seq = seq->next; } /* * Set the client and server FIN sequences. */ seq_t *fin_seq = NULL; /* The actual FIN sequence. */ u_int8_t fin_dir = 0; /* fin_dir: * 0: Not set; * 1: src_fin_seq is used; * 2: dst_fin_seq is used; */ if (src_fin_seq != NULL && dst_fin_seq == NULL) { fin_seq = src_fin_seq; fin_dir = 1; } else if (src_fin_seq == NULL && dst_fin_seq != NULL) { fin_seq = dst_fin_seq; fin_dir = 2; } else if (src_fin_seq != NULL && dst_fin_seq != NULL) { fin_seq = src_fin_seq; fin_dir = 1; if(compare_sequence_time(src_fin_seq, dst_fin_seq) == 1) { fin_seq = dst_fin_seq; fin_dir = 2; } } else { fin_seq = NULL; fin_dir = 0; } /* * First step: find requests */ packet_t *pkt; request_t *req; response_t *rsp; int reqn = 0; // Number of requests. int rspn = 0; // Number of responses. http_pair_t *new_http = NULL; seq_t *seq_next = NULL; /* for temp */ seq_t *first_seq = NULL; /* Set seq and seq_next */ seq = f->order->src; if( seq != NULL) { seq_next = seq->next; } else { seq_next = NULL; /* NULL */ } if (fin_seq != NULL && seq != NULL) { /*A FIN packet exists.*/ while(compare_sequence_time(seq, fin_seq) < 0) { pkt = seq->pkt; if(pkt != NULL && pkt->http == HTTP_REQ) { /* When a new HTTP request is found, * create a HTTP pair object, then add the object to * flow's HTTP chain. */ reqn++; /* new HTTP pair object*/ new_http = http_new(); first_seq = seq; new_http->req_fb_sec = seq->cap_sec; new_http->req_fb_usec = seq->cap_usec; new_http->req_lb_sec = seq->cap_sec; new_http->req_lb_usec = seq->cap_usec; /* Add the object to flow's HTTP chain */ flow_add_http(f, new_http); /* new request object */ req = http_request_new(); /* Add the request object to the foregoing HTTP pair object */ http_add_request(new_http, req); /* parse and write values to foregoing request object */ http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } else { /*Omit the TCP handshake sequences.*/ if(new_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if( new_http != NULL ) { if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\ compare_sequence_time(seq_next, fin_seq) >= 0 ){ //assert(seq->nxt_seq != 0); if( seq->nxt_seq != 0){ new_http->req_total_len = seq->nxt_seq - first_seq->seq; new_http->req_body_len = 0; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } /* Continue to next sequence.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } else { /* No FIN packet found.*/ while(seq != NULL) { pkt = seq->pkt; if(pkt != NULL && pkt->http == HTTP_REQ) { /* When a new HTTP request is found, * create a HTTP pair object, then add the object to * flow's HTTP chain. */ reqn++; /* new HTTP pair object*/ new_http = http_new(); first_seq = seq; new_http->req_fb_sec = seq->cap_sec; new_http->req_fb_usec = seq->cap_usec; new_http->req_lb_sec = seq->cap_sec; new_http->req_lb_usec = seq->cap_usec; /* Add the object to flow's HTTP chain */ flow_add_http(f, new_http); /* new request object */ req = http_request_new(); /* Add the request object to the foregoing HTTP pair object */ http_add_request(new_http, req); /* parse and write values to foregoing request object */ http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } else { if(new_http == NULL) { /*Omit the TCP handshake sequences.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if( new_http != NULL ) { if( seq_next == NULL || seq_next->pkt != NULL ) { //assert(seq->nxt_seq != 0); if( seq->nxt_seq != 0){ new_http->req_total_len = seq->nxt_seq - first_seq->seq; new_http->req_body_len = 0; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } /*Continue to next sequence.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } /* If no responses found, we treat the flow as invalid and stop parsing */ if(reqn == 0) return 1; /* Second step: find responses */ http_pair_t *tmp = f->http_f; http_pair_t *found_http = NULL; seq = f->order->dst; if( seq != NULL) seq_next = seq->next; else seq_next = NULL; /* NULL */ if(fin_seq != NULL && seq != NULL){ /*There is FIN packet.*/ while(compare_sequence_time(seq, fin_seq) < 0) { pkt = seq->pkt; if ( pkt != NULL && pkt->http == HTTP_RSP) { /* * Similar to the request parsing, a new response is * added to the first pair without response */ rspn++; /* Try to find the first pair without response */ while(tmp != NULL) { if(tmp->response_header == NULL) break; tmp = tmp->next; } if(tmp == NULL) /* no response empty, then return */ return 1; else { /*Found!*/ found_http = tmp; first_seq = seq; found_http->rsp_fb_sec = seq->cap_sec; found_http->rsp_fb_usec = seq->cap_usec; rsp = http_response_new(); http_add_response(found_http, rsp); http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } } else { if(found_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if ( found_http != NULL ) { /*first_seq != NULL*/ if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\ compare_sequence_time(seq_next, fin_seq) >= 0 ) { found_http->rsp_lb_sec = seq->cap_sec; found_http->rsp_lb_usec = seq->cap_usec; //assert( seq->nxt_seq != 0 ); if(seq->nxt_seq != 0){ found_http->rsp_total_len = seq->nxt_seq - first_seq->seq; //printf("%d,%d", found_http->rsp_total_len, found_http->response_header->hdlen); //assert(found_http->rsp_total_len >= found_http->response_header->hdlen); found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } else { /*There is no FIN packet.*/ while(seq != NULL) { pkt = seq->pkt; if ( pkt != NULL && pkt->http == HTTP_RSP ) { /* * Similar to the request parsing, a new response is * added to the first pair without response */ rspn++; /* Try to find the first pair without response */ while(tmp != NULL) { if(tmp->response_header == NULL) break; tmp = tmp->next; } if(tmp == NULL) /* no response empty, then return */ return 1; else { /*Found!*/ found_http = tmp; first_seq = seq; found_http->rsp_fb_sec = seq->cap_sec; found_http->rsp_fb_usec = seq->cap_usec; rsp = http_response_new(); http_add_response(found_http, rsp); http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } } else { if(found_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if ( found_http != NULL ) { /*first_seq != NULL*/ if( seq_next == NULL || seq_next->pkt != NULL ) { found_http->rsp_lb_sec = seq->cap_sec; found_http->rsp_lb_usec = seq->cap_usec; //assert( seq->nxt_seq != 0 ); if(seq->nxt_seq != 0){ found_http->rsp_total_len = seq->nxt_seq - first_seq->seq; assert(found_http->rsp_total_len >= found_http->response_header->hdlen); found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } return 0; }