예제 #1
0
static void request(const std::string &url,
					LLURLRequest::ERequestAction method,
					BodyData *body,
					HippoRestHandler *handler, float timeout)
{
	if (!LLHTTPClient::hasPump())
	{
		// !!! responder->completed(U32_MAX, "No pump", LLSD());
		return;
	}
	LLPumpIO::chain_t chain;

	LLURLRequest *req = new LLURLRequest(method, url);
	req->checkRootCertificate(true);

	/*
	// Insert custom headers if the caller sent any
	if (headers.isMap())
	{
		LLSD::map_const_iterator iter = headers.beginMap();
		LLSD::map_const_iterator end  = headers.endMap();
 
		for (; iter != end; ++iter)
		{
			std::ostringstream header;
			//if the header is "Pragma" with no value
			//the caller intends to force libcurl to drop
			//the Pragma header it so gratuitously inserts
			//Before inserting the header, force libcurl
			//to not use the proxy (read: llurlrequest.cpp)
			static const std::string PRAGMA("Pragma");
			if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
			{
				req->useProxy(false);
			}
			header << iter->first << ": " << iter->second.asString() ;
			lldebugs << "header = " << header.str() << llendl;
			req->addHeader(header.str().c_str());
		}
	}
	*/

	if ((method != LLURLRequest::HTTP_PUT) && (method != LLURLRequest::HTTP_POST)) {
		std::string accept = "Accept: ";
		accept += handler->getAcceptMimeType();
		req->addHeader(accept.c_str());
	}

	req->setCallback(new HippoRestComplete(handler));

	if ((method == LLURLRequest::HTTP_PUT) || (method == LLURLRequest::HTTP_POST)) {
		std::string content = "Content-Type: ";
		content += body->getContentMimeType();
		req->addHeader(content.c_str());
		chain.push_back(LLIOPipe::ptr_t(body));
	}

	chain.push_back(LLIOPipe::ptr_t(req));
	LLHTTPClient::getPump().addChain(chain, timeout);
}
예제 #2
0
		std::string makeRequest(
			const std::string& name,
			const std::string& httpRequest,
			bool timeout = false)
		{
			LLPipeStringInjector* injector = new LLPipeStringInjector(httpRequest);
			LLPipeStringExtractor* extractor = new LLPipeStringExtractor();
			
			apr_pool_t* pool;
			apr_pool_create(&pool, NULL);

			LLPumpIO* pump;
			pump = new LLPumpIO(pool);

			LLPumpIO::chain_t chain;
			LLSD context;

			chain.push_back(LLIOPipe::ptr_t(injector));
			LLIOHTTPServer::createPipe(chain, mRoot, LLSD());
			chain.push_back(LLIOPipe::ptr_t(extractor));

			pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);

			pumpPipe(pump, 10);
			if(mResponse.notNull() && (! timeout)) 
			{
				mResponse->result(mResult);
				mResponse = NULL;
			}
			pumpPipe(pump, 10);
			
			std::string httpResult = extractor->string();

			chain.clear();
			delete pump;
			apr_pool_destroy(pool);

			if(mResponse.notNull() && timeout)
			{
				mResponse->result(mResult);
				mResponse = NULL;
			}
			
			return httpResult;
		}
static void request(
	const std::string& url,
	LLURLRequest::ERequestAction method,
	Injector* body_injector,
	LLCurl::ResponderPtr responder,
	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
	const LLSD& headers = LLSD()
    )
{
	if (!LLHTTPClient::hasPump())
	{
		responder->completed(U32_MAX, "No pump", LLSD());
		return;
	}
	LLPumpIO::chain_t chain;

	LLURLRequest* req = new LLURLRequest(method, url);
	if(!req->isValid())//failed
	{
		delete req ;
		return ;
	}

	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);

	
	lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
		<< headers << llendl;

	// Insert custom headers if the caller sent any
	if (headers.isMap())
	{
		if (headers.has("Cookie"))
		{
			req->allowCookies();
		}

        LLSD::map_const_iterator iter = headers.beginMap();
        LLSD::map_const_iterator end  = headers.endMap();

        for (; iter != end; ++iter)
        {
            std::ostringstream header;
            //if the header is "Pragma" with no value
            //the caller intends to force libcurl to drop
            //the Pragma header it so gratuitously inserts
            //Before inserting the header, force libcurl
            //to not use the proxy (read: llurlrequest.cpp)
			static const std::string PRAGMA("Pragma");
			if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
            {
                req->useProxy(false);
            }
            header << iter->first << ": " << iter->second.asString() ;
            lldebugs << "header = " << header.str() << llendl;
            req->addHeader(header.str().c_str());
        }
    }

	// Check to see if we have already set Accept or not. If no one
	// set it, set it to application/llsd+xml since that's what we
	// almost always want.
	if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST )
	{
		static const std::string ACCEPT("Accept");
		if(!headers.has(ACCEPT))
		{
			req->addHeader("Accept: application/llsd+xml");
		}
	}

	if (responder)
	{
		responder->setURL(url);
	}

	req->setCallback(new LLHTTPClientURLAdaptor(responder));

	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem)
	{
		req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
								gMessageSystem->mPort).c_str());
   	}

	if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
	{
		static const std::string CONTENT_TYPE("Content-Type");
		if(!headers.has(CONTENT_TYPE))
		{
			// If the Content-Type header was passed in, it has
			// already been added as a header through req->addHeader
			// in the loop above. We defer to the caller's wisdom, but
			// if they did not specify a Content-Type, then ask the
			// injector.
			req->addHeader(
				llformat(
					"Content-Type: %s",
					body_injector->contentType()).c_str());
		}
   		chain.push_back(LLIOPipe::ptr_t(body_injector));
	}

	chain.push_back(LLIOPipe::ptr_t(req));

	theClientPump->addChain(chain, timeout);
}
// virtual
LLIOPipe::EStatus LLIOServerSocket::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	LL_RECORD_BLOCK_TIME(FTM_PROCESS_SERVER_SOCKET);
	PUMP_DEBUG;
	if(!pump)
	{
		LL_WARNS() << "Need a pump for server socket." << LL_ENDL;
		return STATUS_ERROR;
	}
	if(!mInitialized)
	{
		PUMP_DEBUG;
		// This segment sets up the pump so that we do not call
		// process again until we have an incoming read, aka connect()
		// from a remote host.
		LL_DEBUGS() << "Initializing poll descriptor for LLIOServerSocket."
				 << LL_ENDL;
		apr_pollfd_t poll_fd;
		poll_fd.p = NULL;
		poll_fd.desc_type = APR_POLL_SOCKET;
		poll_fd.reqevents = APR_POLLIN;
		poll_fd.rtnevents = 0x0;
		poll_fd.desc.s = mListenSocket->getSocket();
		poll_fd.client_data = NULL;
		pump->setConditional(this, &poll_fd);
		mInitialized = true;
		return STATUS_OK;
	}

	// we are initialized, and told to process, so we must have a
	// socket waiting for a connection.
	LL_DEBUGS() << "accepting socket" << LL_ENDL;

	PUMP_DEBUG;
	apr_status_t status;
	LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket));
	//EStatus rv = STATUS_ERROR;
	if(llsocket && status == APR_SUCCESS)
	{
		PUMP_DEBUG;

		apr_sockaddr_t* remote_addr;
		apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket());
		
		char* remote_host_string;
		apr_sockaddr_ip_get(&remote_host_string, remote_addr);

		LLSD context;
		context["remote-host"] = remote_host_string;
		context["remote-port"] = remote_addr->port;

		LLPumpIO::chain_t chain;
		chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
		if(mReactor->build(chain, context))
		{
			chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
			pump->addChain(chain, mResponseTimeout);
		}
		else
		{
			LL_WARNS() << "Unable to build reactor to socket." << LL_ENDL;
		}
	}
	else
	{
		char buf[256];
		LL_WARNS() << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << LL_ENDL;
	}

	PUMP_DEBUG;
	// This needs to always return success, lest it get removed from
	// the pump.
	return STATUS_OK;
}
예제 #5
0
// virtual
LLIOPipe::EStatus LLIOServerSocket::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	PUMP_DEBUG;
	LLMemType m1(LLMemType::MTYPE_IO_TCP);
	if(!pump)
	{
		llwarns << "Need a pump for server socket." << llendl;
		return STATUS_ERROR;
	}
	if(!mInitialized)
	{
		PUMP_DEBUG;
		// This segment sets up the pump so that we do not call
		// process again until we have an incoming read, aka connect()
		// from a remote host.
		lldebugs << "Initializing poll descriptor for LLIOServerSocket."
				 << llendl;
		apr_pollfd_t poll_fd;
		poll_fd.p = NULL;
		poll_fd.desc_type = APR_POLL_SOCKET;
		poll_fd.reqevents = APR_POLLIN;
		poll_fd.rtnevents = 0x0;
		poll_fd.desc.s = mListenSocket->getSocket();
		poll_fd.client_data = NULL;
		pump->setConditional(this, &poll_fd);
		mInitialized = true;
		return STATUS_OK;
	}

	// we are initialized, and told to process, so we must have a
	// socket waiting for a connection.
	lldebugs << "accepting socket" << llendl;

	PUMP_DEBUG;
	apr_pool_t* new_pool = NULL;
	apr_status_t status = apr_pool_create(&new_pool, mPool);
	apr_socket_t* socket = NULL;
	status = apr_socket_accept(
		&socket,
		mListenSocket->getSocket(),
		new_pool);
	LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool));
	//EStatus rv = STATUS_ERROR;
	if(llsocket)
	{
		PUMP_DEBUG;

		apr_sockaddr_t* remote_addr;
		apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
		
		char* remote_host_string;
		apr_sockaddr_ip_get(&remote_host_string, remote_addr);

		LLSD context;
		context["remote-host"] = remote_host_string;
		context["remote-port"] = remote_addr->port;

		LLPumpIO::chain_t chain;
		chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
		if(mReactor->build(chain, context))
		{
			chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
			pump->addChain(chain, mResponseTimeout);
			status = STATUS_OK;
		}
		else
		{
			llwarns << "Unable to build reactor to socket." << llendl;
		}
	}
	else
	{
		llwarns << "Unable to create linden socket." << llendl;
	}

	PUMP_DEBUG;
	// This needs to always return success, lest it get removed from
	// the pump.
	return STATUS_OK;
}
// virtual
LLIOPipe::EStatus LLSDRPCClient::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	PUMP_DEBUG;
	LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
	if((STATE_NONE == mState) || (!pump))
	{
		// You should have called the call() method already.
		return STATUS_PRECONDITION_NOT_MET;
	}
	EStatus rv = STATUS_DONE;
	switch(mState)
	{
	case STATE_READY:
	{
		PUMP_DEBUG;
//		lldebugs << "LLSDRPCClient::process_impl STATE_READY" << llendl;
		buffer->append(
			channels.out(),
			(U8*)mRequest.c_str(),
			mRequest.length());
		context[CONTEXT_DEST_URI_SD_LABEL] = mURI;
		mState = STATE_WAITING_FOR_RESPONSE;
		break;
	}
	case STATE_WAITING_FOR_RESPONSE:
	{
		PUMP_DEBUG;
		// The input channel has the sd response in it.
		//lldebugs << "LLSDRPCClient::process_impl STATE_WAITING_FOR_RESPONSE"
		//		 << llendl;
		LLBufferStream resp(channels, buffer.get());
		LLSD sd;
		LLSDSerialize::fromNotation(sd, resp, buffer->count(channels.in()));
		LLSDRPCResponse* response = (LLSDRPCResponse*)mResponse.get();
		if (!response)
		{
			mState = STATE_DONE;
			break;
		}
		response->extractResponse(sd);
		if(EPBQ_PROCESS == mQueue)
		{
			LLPumpIO::chain_t chain;
			chain.push_back(mResponse);
			pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
		}
		else
		{
			pump->respond(mResponse.get());
		}
		mState = STATE_DONE;
		break;
	}
	case STATE_DONE:
	default:
		PUMP_DEBUG;
		llinfos << "invalid state to process" << llendl;
		rv = STATUS_ERROR;
		break;
	}
	return rv;
}
예제 #7
0
static void request(
	const std::string& url,
	EHTTPMethod method,
	Injector* body_injector,
	LLCurl::ResponderPtr responder,
	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
	const LLSD& headers = LLSD(),
	bool follow_redirects = true
    )
{
	if (!LLHTTPClient::hasPump())
	{
		if (responder)
		{
			responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
		}
		delete body_injector;
		return;
	}
	LLPumpIO::chain_t chain;

	LLURLRequest* req = new LLURLRequest(method, url, follow_redirects);
	if(!req->isValid())//failed
	{
		if (responder)
		{
			responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
		}
		delete req;
		delete body_injector;
		return;
	}

	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);

	LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;

	// Insert custom headers if the caller sent any
	if (headers.isMap())
	{
		if (headers.has(HTTP_OUT_HEADER_COOKIE))
		{
			req->allowCookies();
		}

		LLSD::map_const_iterator iter = headers.beginMap();
		LLSD::map_const_iterator end  = headers.endMap();

		for (; iter != end; ++iter)
		{
			//if the header is "Pragma" with no value
			//the caller intends to force libcurl to drop
			//the Pragma header it so gratuitously inserts
			//Before inserting the header, force libcurl
			//to not use the proxy (read: llurlrequest.cpp)
			if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
			{
				req->useProxy(false);
			}
			LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
				<< ": " << iter->second.asString() << LL_ENDL;
			req->addHeader(iter->first, iter->second.asString());
		}
	}

	// Check to see if we have already set Accept or not. If no one
	// set it, set it to application/llsd+xml since that's what we
	// almost always want.
	if( method != HTTP_PUT && method != HTTP_POST )
	{
		if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
		{
			req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
		}
	}

	if (responder)
	{
		responder->setURL(url);
		responder->setHTTPMethod(method);
	}

	if (method == HTTP_POST  &&  gMessageSystem)
	{
		req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
					gMessageSystem->mPort));
   	}

	if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
	{
		if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
		{
			// If the Content-Type header was passed in, it has
			// already been added as a header through req->addHeader
			// in the loop above. We defer to the caller's wisdom, but
			// if they did not specify a Content-Type, then ask the
			// injector.
			req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
		}
		chain.push_back(LLIOPipe::ptr_t(body_injector));
	}

	static U64 request_id = 0;
	++request_id;
	req->setCallback(new LLHTTPClientURLAdaptor(responder, request_id));

	chain.push_back(LLIOPipe::ptr_t(req));

	theClientPump->addChain(chain, timeout);
}