Example #1
0
/**
 * @brief Open a LLSocket and do a blocking connect to the chosen host.
 *
 * Checks for a successful connection, and makes sure the connection is closed if it fails.
 *
 * @param host		The host to open the connection to.
 * @return			The created socket.  Will evaluate as NULL if the connection is unsuccessful.
 */
static LLSocket::ptr_t tcp_open_channel(LLHost host)
{
	LLSocket::ptr_t socket = LLSocket::create(NULL, LLSocket::STREAM_TCP);
	bool connected = socket->blockingConnect(host);
	if (!connected)
	{
		tcp_close_channel(&socket);
	}

	return socket;
}
Example #2
0
// static
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
{
	LLSocket::ptr_t rv;
	if(!socket)
	{
		return rv;
	}
	rv = ptr_t(new LLSocket(socket, pool));
	rv->mPort = PORT_EPHEMERAL;
	rv->setNonBlocking();
	return rv;
}
Example #3
0
// static
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
{
	LLMemType m1(LLMemType::MTYPE_IO_TCP);
	LLSocket::ptr_t rv;
	if(!socket)
	{
		return rv;
	}
	rv = ptr_t(new LLSocket(socket, pool));
	rv->mPort = PORT_EPHEMERAL;
	rv->setOptions();
	return rv;
}
Example #4
0
/**
 * @brief Send one TCP packet and receive one in return.
 *
 * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking
 * operation would impact the operation of the viewer.
 *
 * @param handle_ptr 	Pointer to a connected LLSocket of type STREAM_TCP.
 * @param dataout		Data to send.
 * @param outlen		Length of dataout.
 * @param datain		Buffer for received data. Undefined if return value is not APR_SUCCESS.
 * @param maxinlen		Maximum possible length of received data.  Short reads are allowed.
 * @return 				Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received.
 */
static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen)
{
	apr_socket_t* apr_socket = handle->getSocket();
	apr_status_t rv = APR_SUCCESS;

	apr_size_t expected_len = outlen;

	handle->setBlocking(1000);

  	rv = apr_socket_send(apr_socket, dataout, &outlen);
	if (APR_SUCCESS != rv)
	{
		LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << LL_ENDL;
		ll_apr_warn_status(rv);
	}
	else if (expected_len != outlen)
	{
		LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len <<
				" Sent: " << outlen << LL_ENDL;
		rv = -1;
	}

	if (APR_SUCCESS == rv)
	{
		expected_len = maxinlen;
		rv = apr_socket_recv(apr_socket, datain, &maxinlen);
		if (rv != APR_SUCCESS)
		{
			LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL;
			ll_apr_warn_status(rv);
		}
		else if (expected_len < maxinlen)
		{
			LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len <<
					" Received: " << maxinlen << LL_ENDL;
			rv = -1;
		}
	}

	handle->setNonBlocking();

	return rv;
}
// static
LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket)
{
	if (!listen_socket->getSocket())
	{
		status = APR_ENOSOCKET;
		return LLSocket::ptr_t();
	}
	LLSocket::ptr_t rv(new LLSocket);
	LL_DEBUGS() << "accepting socket" << LL_ENDL;
	status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool());
	if (status != APR_SUCCESS)
	{
		rv->mSocket = NULL;
		rv.reset();
		return rv;
	}
	rv->mPort = PORT_EPHEMERAL;
	rv->setNonBlocking();
	return rv;
}
Example #6
0
// static
LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket)
{
	LLMemType m1(LLMemType::MTYPE_IO_TCP);
	if (!listen_socket->getSocket())
	{
		status = APR_ENOSOCKET;
		return LLSocket::ptr_t();
	}
	LLSocket::ptr_t rv(new LLSocket);
	lldebugs << "accepting socket" << llendl;
	status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool());
	if (status != APR_SUCCESS)
	{
		rv->mSocket = NULL;
		rv.reset();
		return rv;
	}
	rv->mPort = PORT_EPHEMERAL;
	rv->setNonBlocking();
	return rv;
}
Example #7
0
// static
LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
{
	LLMemType m1(LLMemType::MTYPE_IO_TCP);
	LLSocket::ptr_t rv;
	apr_socket_t* socket = NULL;
	apr_pool_t* new_pool = NULL;
	apr_status_t status = APR_EGENERAL;

	// create a pool for the socket
	status = apr_pool_create(&new_pool, pool);
	if(ll_apr_warn_status(status))
	{
		if(new_pool) apr_pool_destroy(new_pool);
		return rv;
	}

	if(STREAM_TCP == type)
	{
		status = apr_socket_create(
			&socket,
			APR_INET,
			SOCK_STREAM,
			APR_PROTO_TCP,
			new_pool);
	}
	else if(DATAGRAM_UDP == type)
	{
		status = apr_socket_create(
			&socket,
			APR_INET,
			SOCK_DGRAM,
			APR_PROTO_UDP,
			new_pool);
	}
	else
	{
		if(new_pool) apr_pool_destroy(new_pool);
		return rv;
	}
	if(ll_apr_warn_status(status))
	{
		if(new_pool) apr_pool_destroy(new_pool);
		return rv;
	}
	rv = ptr_t(new LLSocket(socket, new_pool));
	if(port > 0)
	{
		apr_sockaddr_t* sa = NULL;
		status = apr_sockaddr_info_get(
			&sa,
			APR_ANYADDR,
			APR_UNSPEC,
			port,
			0,
			new_pool);
		if(ll_apr_warn_status(status))
		{
			rv.reset();
			return rv;
		}
		// This allows us to reuse the address on quick down/up. This
		// is unlikely to create problems.
		ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
		status = apr_socket_bind(socket, sa);
		if(ll_apr_warn_status(status))
		{
			rv.reset();
			return rv;
		}
		lldebugs << "Bound " << ((DATAGRAM_UDP == type) ? "udp" : "tcp")
				 << " socket to port: " << sa->port << llendl;
		if(STREAM_TCP == type)
		{
			// If it's a stream based socket, we need to tell the OS
			// to keep a queue of incoming connections for ACCEPT.
			lldebugs << "Setting listen state for socket." << llendl;
			status = apr_socket_listen(
				socket,
				LL_DEFAULT_LISTEN_BACKLOG);
			if(ll_apr_warn_status(status))
			{
				rv.reset();
				return rv;
			}
		}
	}
	else
	{
		// we need to indicate that we have an ephemeral port if the
		// previous calls were successful. It will
		port = PORT_EPHEMERAL;
	}
	rv->mPort = port;
	rv->setOptions();
	return rv;
}