Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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 */
Ejemplo n.º 4
0
/* 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;
}