示例#1
0
void HshaServerIO :: IOFunc(int accepted_fd) {
    UThreadSocket_t * socket = scheduler_->CreateSocket(accepted_fd);
    UThreadTcpStream stream;
    stream.Attach(socket);
    UThreadSetSocketTimeout(*socket, config_->GetSocketTimeoutMS()); 
    HshaServerStat::TimeCost time_cost;

    while (true) {
        hsha_server_stat_->io_read_requests_++;
        HttpRequest * request = new HttpRequest;
        int socket_ret = HttpProto::RecvReq(stream, request);
        if (socket_ret != 0) {
            delete request;
            hsha_server_stat_->io_read_fails_++;
            hsha_server_stat_->rpc_time_costs_count_++;
            //phxrpc::log(LOG_ERR, "%s read request fail, fd %d", __func__, accepted_fd);
            break;
        }

        hsha_server_stat_->io_read_bytes_ += request->GetContent().size();

        if (!data_flow_->CanPushRequest(config_->GetMaxQueueLength())) {
            delete request;
            hsha_server_stat_->queue_full_rejected_after_accepted_fds_++;
            break;
        }

        if (!hsha_server_qos_->CanEnqueue()) {
            //fast reject don't cal rpc_time_cost;
            delete request;
            hsha_server_stat_->enqueue_fast_rejects_++;
            //phxrpc::log(LOG_ERR, "%s fast reject, can't enqueue, fd %d", __func__, accepted_fd);
            break;
        }

        //if have enqueue, request will be deleted after pop.
        bool is_keep_alive = request->IsKeepAlive();
        std::string version = string(request->GetVersion() != nullptr ? request->GetVersion() : "");

        hsha_server_stat_->inqueue_push_requests_++;
        data_flow_->PushRequest((void *)socket, request);
        //if is uthread worker mode, need notify.
        worker_pool_->Notify();
        UThreadSetArgs(*socket, nullptr);

        UThreadWait(*socket, config_->GetSocketTimeoutMS());
        if (UThreadGetArgs(*socket) == nullptr) {
            //timeout
            hsha_server_stat_->worker_timeouts_++;
            hsha_server_stat_->rpc_time_costs_count_++;

            //because have enqueue, so socket will be closed after pop.
            socket = stream.DetachSocket(); 
            UThreadLazyDestory(*socket);

            //phxrpc::log(LOG_ERR, "%s timeout, fd %d sockettimeoutms %d", 
                    //__func__, accepted_fd, config_->GetSocketTimeoutMS());
            break;
        }

        hsha_server_stat_->io_write_responses_++;
        HttpResponse * response = (HttpResponse *)UThreadGetArgs(*socket);
        HttpProto::FixRespHeaders(is_keep_alive, version.c_str(), response);
        socket_ret = HttpProto::SendResp(stream, *response);
        hsha_server_stat_->io_write_bytes_ += response->GetContent().size();
        delete response;

        hsha_server_stat_->rpc_time_costs_count_++;

        if (socket_ret != 0) {
            hsha_server_stat_->io_write_fails_++;
        }

        if(!is_keep_alive || (socket_ret != 0)) {
            break;
        } else {
            hsha_server_stat_->rpc_time_costs_ += time_cost.Cost();
        }
    }

    hsha_server_stat_->rpc_time_costs_ += time_cost.Cost();
    hsha_server_stat_->hold_fds_--;
}
static ngx_int_t ngx_http_cxxmvc_handler(ngx_http_request_t *r)
{
	using dragon::kHttp_Method_Get;
	using dragon::kResponseTypeRedirect;
	using dragon::HeaderList;
	using dragon::CookieList;
	using dragon::StringRef;
	using dragon::HttpRequest;
	using dragon::HttpResponse;

	ngx_buf_t *buf = NULL;
	ngx_chain_t out;

	unsigned uriLen = r->uri.len;
	if (r->args.len > 0) 
		uriLen = r->uri.len + r->args.len + 1;
	
	struct sockaddr_in *sin;
	ngx_addr_t          addr;
	addr.sockaddr = r->connection->sockaddr;
	addr.socklen  = r->connection->socklen;
	sin = (struct sockaddr_in *)addr.sockaddr;
	char *ip = inet_ntoa(sin->sin_addr);

	StringRef IP(ip, strlen(ip));
	StringRef routingUrl((const char *)r->uri.data, uriLen);
	StringRef userAgent;
	if (r->headers_in.user_agent)
		userAgent = StringRef((const char *)r->headers_in.user_agent->value.data, r->headers_in.user_agent->value.len);
	
	std::string userCookie = ngx_http_get_cookie(r);
	std::string lang       = ngx_http_get_language(r);

	HttpRequest  req;
	HttpResponse res;

	req.SetMethod(kHttp_Method_Get);
	req.SetUrl(routingUrl);
	req.SetIp(IP);
	//req.SetHost(StringRef(host, strlen(host)));
	req.SetUserAgent(userAgent);
	req.SetUserCookie(StringRef(userCookie.c_str(), userCookie.length()));
	req.SetAcceptLanguage(StringRef(lang.c_str(), lang.length()));
        req.ParseCookie();

	DE.ResponseRequest(req, res);

	ngx_str_t k = ngx_string("X-Powered-By");
	ngx_str_t v = ngx_string("cxxmvc/0.1");;
	ngx_http_add_header(r, &v, &k);

	if (res.GetResponseType() == kResponseTypeRedirect)
	{
		ngx_str_t k = ngx_string("location");
		ngx_str_t v = {res.GetContent().length(), (u_char *)res.GetContent().c_str()};
		ngx_http_add_header(r, &v, &k);
	}

	HeaderList headers = res.GetHeaders();
	if (headers.size() > 0) 
	{
		HeaderList::iterator iter;
		HeaderList::iterator end = headers.end();
		for (iter = headers.begin(); iter != end; ++iter)
		{		
			ngx_str_t k;
			ngx_str_t v; 

			k.data = (u_char *)ngx_pcalloc(r->pool, iter->first.length()+1);
			k.len  = iter->first.length();
			strcpy((char *)k.data, (const char *)iter->first.c_str());

			v.data = (u_char *)ngx_pcalloc(r->pool, iter->second.length()+1);
			v.len  = iter->second.length();
			strcpy((char *)v.data, (const char *)iter->second.c_str());

		//	std::cout << "key : "<< k.data << std::endl;
		//	std::cout << "value : " << v.data << std::endl;

			ngx_http_add_header(r, &v, &k);
		}
	}

	CookieList cookies = res.GetCookies();
	if (cookies.size() > 0)
	{
		CookieList::iterator iter;
		CookieList::iterator end = cookies.end();
		for (iter = cookies.begin(); iter != end; ++iter)
		{
			ngx_str_t v; 

			v.data = (u_char *)ngx_pcalloc(r->pool, iter->length()+1);
			v.len  = iter->length();
			strcpy((char *)v.data, (const char *)iter->c_str());

			ngx_http_add_cookie(r, v);
		}
	}

	r->headers_out.status             = res.GetStatusCode();
    	r->headers_out.content_type.len   = res.GetContentType().length();
	r->headers_out.content_type.data  = (u_char *)res.GetContentType().c_str();

	if (res.GetDetaRef().length() > 0)
		r->headers_out.content_length_n = res.GetDetaRef().length();
        else 
       		r->headers_out.content_length_n = res.GetContent().length();


        ngx_http_send_header(r);

        buf = (ngx_buf_t *)ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

        if (buf == NULL) {
                ngx_log_error(NGX_LOG_ERR,
                              r->connection->log,
                              0,
                              "Failed to allocate response buffer.");
                return NGX_ERROR;
        }

	if (res.GetDetaRef().length() > 0) {
		buf->pos = (u_char *)res.GetDetaRef().data();
       		buf->last = buf->pos + res.GetDetaRef().length();
	} else {
       		buf->pos = (u_char *)res.GetContent().c_str();
        	buf->last = buf->pos + res.GetContent().length();
	}
        buf->memory   = 1; /* content is in read-only memory */
        buf->last_buf = 1; /* there will be no more buffers in the request */

	out.buf    = buf;
	out.next   = NULL;

	return ngx_http_output_filter(r, &out);
}