summaryrefslogtreecommitdiff
path: root/indra/llmessage/net.cpp
diff options
context:
space:
mode:
authorLogan Dethrow <log@lindenlab.com>2011-06-21 17:09:12 -0400
committerLogan Dethrow <log@lindenlab.com>2011-06-21 17:09:12 -0400
commit20100ba38c6d3fa16ab11be2ed326ab0964c4c21 (patch)
tree6f249a693990463fc7e057f29a106db6e20bb691 /indra/llmessage/net.cpp
parent6ce2c20a06e32825f4e4260575059a9867510ecd (diff)
Refactored SOCKS 5 handshake to use existing LLSocket class.
Diffstat (limited to 'indra/llmessage/net.cpp')
-rw-r--r--indra/llmessage/net.cpp219
1 files changed, 59 insertions, 160 deletions
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp
index a51d80ff48..366a1835ca 100644
--- a/indra/llmessage/net.cpp
+++ b/indra/llmessage/net.cpp
@@ -189,93 +189,6 @@ U32 ip_string_to_u32(const char* ip_string)
//////////////////////////////////////////////////////////////////////////////////////////
#if LL_WINDOWS
-
-int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen)
-{
- int result;
- result = send(handle, dataout, outlen, 0);
- if (result != outlen)
- {
- S32 err = WSAGetLastError();
- llwarns << "Error sending data to proxy control channel, number of bytes sent were " << result << " error code was " << err << llendl;
- return -1;
- }
-
- result = recv(handle, datain, maxinlen, 0);
- if (result != maxinlen)
- {
- S32 err = WSAGetLastError();
- llwarns << "Error receiving data from proxy control channel, number of bytes received were " << result << " error code was " << err << llendl;
- return -1;
- }
-
- return 0;
-}
-
-S32 tcp_open_channel(LLHost host)
-{
- // Open a TCP channel
- // Jump through some hoops to ensure that if the request hosts is down
- // or not reachable connect() does not block
-
- S32 handle;
- handle = socket(AF_INET, SOCK_STREAM, 0);
- if (INVALID_SOCKET == handle)
- {
- llwarns << "Error opening TCP control socket, socket() returned "
- << WSAGetLastError() << ", " << DecodeError(WSAGetLastError()) << llendl;
- return -1;
- }
-
- struct sockaddr_in address;
- address.sin_port = htons(host.getPort());
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = host.getAddress();
-
- // Non blocking
- WSAEVENT hEvent = WSACreateEvent();
- WSAEventSelect(handle, hEvent, FD_CONNECT) ;
- connect(handle, (struct sockaddr*)&address, sizeof(address)) ;
- // Wait for 5 seconds, if we can't get a TCP channel open in this
- // time frame then there is something badly wrong.
- WaitForSingleObject(hEvent, 1000 * 5); // 5 seconds time out
-
- WSANETWORKEVENTS netevents;
- WSAEnumNetworkEvents(handle, hEvent, &netevents);
-
- // Check the async event status to see if we connected
- if ((netevents.lNetworkEvents & FD_CONNECT) == FD_CONNECT)
- {
- if (netevents.iErrorCode[FD_CONNECT_BIT] != 0)
- {
- llwarns << "Unable to open TCP channel, WSA returned an error code of " << netevents.iErrorCode[FD_CONNECT_BIT] << llendl;
- WSACloseEvent(hEvent);
- tcp_close_channel(handle);
- return -1;
- }
-
- // Now we are connected disable non blocking
- // we don't need support an async interface as
- // currently our only consumer (socks5) will make one round
- // of packets then just hold the connection open
- WSAEventSelect(handle, hEvent, NULL) ;
- unsigned long NonBlock = 0;
- ioctlsocket(handle, FIONBIO, &NonBlock);
-
- return handle;
- }
-
- llwarns << "Unable to open TCP channel, Timeout is the host up?" << netevents.iErrorCode[FD_CONNECT_BIT] << llendl;
- tcp_close_channel(handle);
- return -1;
-}
-
-void tcp_close_channel(S32 handle)
-{
- llinfos << "Closing TCP channel" << llendl;
- shutdown(handle, SD_BOTH);
- closesocket(handle);
-}
S32 start_net(S32& socket_out, int& nPort)
{
@@ -473,79 +386,6 @@ BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, i
#else
-
-int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen)
-{
- if (send(handle, dataout, outlen, 0) != outlen)
- {
- llwarns << "Error sending data to proxy control channel" << llendl;
- return -1;
- }
-
- if (recv(handle, datain, maxinlen, 0) != maxinlen)
- {
- llwarns << "Error receiving data to proxy control channel" << llendl;
- return -1;
- }
-
- return 0;
-}
-
-S32 tcp_open_channel(LLHost host)
-{
- S32 handle;
- handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (-1 == handle)
- {
- llwarns << "Error opening TCP control socket, socket() returned " << handle << "error code: " << errno << llendl;
- return -1;
- }
-
- struct sockaddr_in address;
- address.sin_port = htons(host.getPort());
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = host.getAddress();
-
- // Set the socket to non blocking for the connect()
- int flags = fcntl(handle, F_GETFL, 0);
- fcntl(handle, F_SETFL, flags | O_NONBLOCK);
-
- S32 error = connect(handle, (sockaddr*)&address, sizeof(address));
- if (error && (errno != EINPROGRESS))
- {
- llwarns << "Unable to open TCP channel, error code: " << errno << llendl;
- tcp_close_channel(handle);
- return -1;
- }
-
- struct timeval timeout;
- timeout.tv_sec = 5; // Maximum time to wait for the connect() to complete
- timeout.tv_usec = 0;
- fd_set fds;
- FD_ZERO(&fds);
- FD_SET(handle, &fds);
-
- // See if we have connected or time out after 5 seconds
- S32 rc = select(sizeof(fds)*8, NULL, &fds, NULL, &timeout);
-
- if (rc != 1) // we require exactly one descriptor to be set
- {
- llwarns << "Unable to open TCP channel" << llendl;
- tcp_close_channel(handle);
- return -1;
- }
-
- // Return the socket to blocking operations
- fcntl(handle, F_SETFL, flags);
-
- return handle;
-}
-
-void tcp_close_channel(S32 handle)
-{
- close(handle);
-}
-
// Create socket, make non-blocking
S32 start_net(S32& socket_out, int& nPort)
{
@@ -824,4 +664,63 @@ BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient,
#endif
+int tcp_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_size_t expected_len = outlen;
+
+ apr_socket_opt_set(apr_socket, APR_SO_NONBLOCK, -5); // Blocking connection, 5 second timeout
+ apr_socket_timeout_set(apr_socket, (APR_USEC_PER_SEC * 5));
+
+ rv = apr_socket_send(apr_socket, dataout, &outlen);
+ if (rv != APR_SUCCESS || expected_len != outlen)
+ {
+ llwarns << "Error sending data to proxy control channel" << llendl;
+ ll_apr_warn_status(rv);
+ return -1;
+ }
+
+ expected_len = maxinlen;
+ do
+ {
+ rv = apr_socket_recv(apr_socket, datain, &maxinlen);
+ llinfos << "Receiving packets." << llendl;
+ llwarns << "Proxy control channel status: " << rv << llendl;
+ } while (APR_STATUS_IS_EAGAIN(rv));
+
+ if (rv != APR_SUCCESS)
+ {
+ llwarns << "Error receiving data from proxy control channel, status: " << rv << llendl;
+ llwarns << "Received " << maxinlen << " bytes." << llendl;
+ ll_apr_warn_status(rv);
+ return rv;
+ }
+ else if (expected_len != maxinlen)
+ {
+ llwarns << "Incorrect data received length in proxy control channel" << llendl;
+ return -1;
+ }
+
+ return 0;
+}
+
+LLSocket::ptr_t tcp_open_channel(LLHost host)
+{
+ LLSocket::ptr_t socket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
+ bool connected = socket->blockingConnect(host);
+ if (!connected)
+ {
+ tcp_close_channel(socket);
+ }
+
+ return socket;
+}
+
+void tcp_close_channel(LLSocket::ptr_t handle)
+{
+ handle.reset();
+}
+
//EOF