diff options
Diffstat (limited to 'linden/indra/llmessage')
-rw-r--r-- | linden/indra/llmessage/CMakeLists.txt | 2 | ||||
-rw-r--r-- | linden/indra/llmessage/llcurl.cpp | 40 | ||||
-rw-r--r-- | linden/indra/llmessage/llpacketring.cpp | 56 | ||||
-rw-r--r-- | linden/indra/llmessage/llpacketring.h | 3 | ||||
-rw-r--r-- | linden/indra/llmessage/llsocks5.cpp | 210 | ||||
-rw-r--r-- | linden/indra/llmessage/llsocks5.h | 248 | ||||
-rw-r--r-- | linden/indra/llmessage/message.cpp | 8 | ||||
-rw-r--r-- | linden/indra/llmessage/message.h | 14 | ||||
-rw-r--r-- | linden/indra/llmessage/net.cpp | 158 | ||||
-rw-r--r-- | linden/indra/llmessage/net.h | 3 |
10 files changed, 731 insertions, 11 deletions
diff --git a/linden/indra/llmessage/CMakeLists.txt b/linden/indra/llmessage/CMakeLists.txt index 9965191..b3f2b4c 100644 --- a/linden/indra/llmessage/CMakeLists.txt +++ b/linden/indra/llmessage/CMakeLists.txt | |||
@@ -98,6 +98,7 @@ set(llmessage_SOURCE_FILES | |||
98 | patch_code.cpp | 98 | patch_code.cpp |
99 | patch_dct.cpp | 99 | patch_dct.cpp |
100 | patch_idct.cpp | 100 | patch_idct.cpp |
101 | llsocks5.cpp | ||
101 | sound_ids.cpp | 102 | sound_ids.cpp |
102 | ) | 103 | ) |
103 | 104 | ||
@@ -198,6 +199,7 @@ set(llmessage_HEADER_FILES | |||
198 | patch_code.h | 199 | patch_code.h |
199 | patch_dct.h | 200 | patch_dct.h |
200 | sound_ids.h | 201 | sound_ids.h |
202 | llsocks5.h | ||
201 | ) | 203 | ) |
202 | 204 | ||
203 | set_source_files_properties(${llmessage_HEADER_FILES} | 205 | set_source_files_properties(${llmessage_HEADER_FILES} |
diff --git a/linden/indra/llmessage/llcurl.cpp b/linden/indra/llmessage/llcurl.cpp index 9ecfee4..b23ef33 100644 --- a/linden/indra/llmessage/llcurl.cpp +++ b/linden/indra/llmessage/llcurl.cpp | |||
@@ -56,6 +56,8 @@ | |||
56 | #include "llsdserialize.h" | 56 | #include "llsdserialize.h" |
57 | #include "llthread.h" | 57 | #include "llthread.h" |
58 | 58 | ||
59 | #include "llsocks5.h" | ||
60 | |||
59 | ////////////////////////////////////////////////////////////////////////////// | 61 | ////////////////////////////////////////////////////////////////////////////// |
60 | /* | 62 | /* |
61 | The trick to getting curl to do keep-alives is to reuse the | 63 | The trick to getting curl to do keep-alives is to reuse the |
@@ -270,6 +272,25 @@ LLCurl::Easy* LLCurl::Easy::getEasy() | |||
270 | // set no DMS caching as default for all easy handles. This prevents them adopting a | 272 | // set no DMS caching as default for all easy handles. This prevents them adopting a |
271 | // multi handles cache if they are added to one. | 273 | // multi handles cache if they are added to one. |
272 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); | 274 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); |
275 | |||
276 | if (LLSocks::getInstance()->isHttpProxyEnabled()) | ||
277 | { | ||
278 | std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); | ||
279 | U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); | ||
280 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXY,address.c_str()); | ||
281 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYPORT,port); | ||
282 | if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) | ||
283 | { | ||
284 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); | ||
285 | if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) | ||
286 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd().c_str()); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); | ||
291 | } | ||
292 | } | ||
293 | |||
273 | ++gCurlEasyCount; | 294 | ++gCurlEasyCount; |
274 | return easy; | 295 | return easy; |
275 | } | 296 | } |
@@ -443,6 +464,24 @@ void LLCurl::Easy::prepRequest(const std::string& url, | |||
443 | // setopt(CURLOPT_VERBOSE, 1); // usefull for debugging | 464 | // setopt(CURLOPT_VERBOSE, 1); // usefull for debugging |
444 | setopt(CURLOPT_NOSIGNAL, 1); | 465 | setopt(CURLOPT_NOSIGNAL, 1); |
445 | 466 | ||
467 | if (LLSocks::getInstance()->isHttpProxyEnabled()) | ||
468 | { | ||
469 | std::string address = LLSocks::getInstance()->getHTTPProxy().getIPString(); | ||
470 | U16 port = LLSocks::getInstance()->getHTTPProxy().getPort(); | ||
471 | setoptString(CURLOPT_PROXY, address.c_str()); | ||
472 | setopt(CURLOPT_PROXYPORT, port); | ||
473 | if (LLSocks::getInstance()->getHttpProxyType() == LLPROXY_SOCKS) | ||
474 | { | ||
475 | setopt(CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); | ||
476 | if(LLSocks::getInstance()->getSelectedAuthMethod()==METHOD_PASSWORD) | ||
477 | setoptString(CURLOPT_PROXYUSERPWD,LLSocks::getInstance()->getProxyUserPwd()); | ||
478 | } | ||
479 | else | ||
480 | { | ||
481 | setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); | ||
482 | } | ||
483 | } | ||
484 | |||
446 | mOutput.reset(new LLBufferArray); | 485 | mOutput.reset(new LLBufferArray); |
447 | setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); | 486 | setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); |
448 | setopt(CURLOPT_WRITEDATA, (void*)this); | 487 | setopt(CURLOPT_WRITEDATA, (void*)this); |
@@ -742,6 +781,7 @@ bool LLCurlRequest::getByteRange(const std::string& url, | |||
742 | if (length > 0) | 781 | if (length > 0) |
743 | { | 782 | { |
744 | std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1); | 783 | std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1); |
784 | //llinfos << "http url: " << url << " " << range << llendl; | ||
745 | easy->slist_append(range.c_str()); | 785 | easy->slist_append(range.c_str()); |
746 | } | 786 | } |
747 | easy->setHeaders(); | 787 | easy->setHeaders(); |
diff --git a/linden/indra/llmessage/llpacketring.cpp b/linden/indra/llmessage/llpacketring.cpp index 7f9617f..e7dad79 100644 --- a/linden/indra/llmessage/llpacketring.cpp +++ b/linden/indra/llmessage/llpacketring.cpp | |||
@@ -43,6 +43,15 @@ | |||
43 | #include "llmessagelog.h" | 43 | #include "llmessagelog.h" |
44 | #include "message.h" | 44 | #include "message.h" |
45 | 45 | ||
46 | #include "llsocks5.h" | ||
47 | |||
48 | #if LL_WINDOWS | ||
49 | #include <winsock2.h> | ||
50 | #else | ||
51 | #include <sys/socket.h> | ||
52 | #include <netinet/in.h> | ||
53 | #endif | ||
54 | |||
46 | /////////////////////////////////////////////////////////// | 55 | /////////////////////////////////////////////////////////// |
47 | LLPacketRing::LLPacketRing () : | 56 | LLPacketRing::LLPacketRing () : |
48 | mUseInThrottle(FALSE), | 57 | mUseInThrottle(FALSE), |
@@ -224,8 +233,25 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap) | |||
224 | else | 233 | else |
225 | { | 234 | { |
226 | // no delay, pull straight from net | 235 | // no delay, pull straight from net |
227 | packet_size = receive_packet(socket, datap); | 236 | if (LLSocks::isEnabled()) |
228 | mLastSender = ::get_sender(); | 237 | { |
238 | proxywrap_t * header; | ||
239 | datap = datap-10; | ||
240 | header = (proxywrap_t *)datap; | ||
241 | packet_size = receive_packet(socket, datap); | ||
242 | mLastSender.setAddress(header->addr); | ||
243 | mLastSender.setPort(ntohs(header->port)); | ||
244 | if (packet_size > 10) | ||
245 | { | ||
246 | packet_size -= 10; | ||
247 | } | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | packet_size = receive_packet(socket, datap); | ||
252 | mLastSender = ::get_sender(); | ||
253 | } | ||
254 | |||
229 | mLastReceivingIF = ::get_receiving_interface(); | 255 | mLastReceivingIF = ::get_receiving_interface(); |
230 | 256 | ||
231 | if (packet_size) // did we actually get a packet? | 257 | if (packet_size) // did we actually get a packet? |
@@ -254,7 +280,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL | |||
254 | BOOL status = TRUE; | 280 | BOOL status = TRUE; |
255 | if (!mUseOutThrottle) | 281 | if (!mUseOutThrottle) |
256 | { | 282 | { |
257 | return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); | 283 | return doSendPacket(h_socket, send_buffer, buf_size, host ); |
258 | } | 284 | } |
259 | else | 285 | else |
260 | { | 286 | { |
@@ -275,7 +301,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL | |||
275 | mOutBufferLength -= packetp->getSize(); | 301 | mOutBufferLength -= packetp->getSize(); |
276 | packet_size = packetp->getSize(); | 302 | packet_size = packetp->getSize(); |
277 | 303 | ||
278 | status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); | 304 | status = doSendPacket(h_socket, packetp->getData(), packet_size, packetp->getHost()); |
279 | 305 | ||
280 | delete packetp; | 306 | delete packetp; |
281 | // Update the throttle | 307 | // Update the throttle |
@@ -284,7 +310,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL | |||
284 | else | 310 | else |
285 | { | 311 | { |
286 | // If the queue's empty, we can just send this packet right away. | 312 | // If the queue's empty, we can just send this packet right away. |
287 | status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); | 313 | status = doSendPacket(h_socket, send_buffer, buf_size, host ); |
288 | packet_size = buf_size; | 314 | packet_size = buf_size; |
289 | 315 | ||
290 | // Update the throttle | 316 | // Update the throttle |
@@ -322,3 +348,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL | |||
322 | 348 | ||
323 | return status; | 349 | return status; |
324 | } | 350 | } |
351 | |||
352 | BOOL LLPacketRing::doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) | ||
353 | { | ||
354 | |||
355 | if (!LLSocks::isEnabled()) | ||
356 | { | ||
357 | return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); | ||
358 | } | ||
359 | |||
360 | proxywrap_t *socks_header = (proxywrap_t *)&mProxyWrappedSendBuffer; | ||
361 | socks_header->rsv = 0; | ||
362 | socks_header->addr = host.getAddress(); | ||
363 | socks_header->port = htons(host.getPort()); | ||
364 | socks_header->atype = ADDRESS_IPV4; | ||
365 | socks_header->frag = 0; | ||
366 | |||
367 | memcpy(mProxyWrappedSendBuffer+10, send_buffer, buf_size); | ||
368 | |||
369 | return send_packet(h_socket,(const char*) mProxyWrappedSendBuffer, buf_size+10, LLSocks::getInstance()->getUDPPproxy().getAddress(), LLSocks::getInstance()->getUDPPproxy().getPort()); | ||
370 | } | ||
diff --git a/linden/indra/llmessage/llpacketring.h b/linden/indra/llmessage/llpacketring.h index 4408abe..5d2c246 100644 --- a/linden/indra/llmessage/llpacketring.h +++ b/linden/indra/llmessage/llpacketring.h | |||
@@ -88,6 +88,9 @@ protected: | |||
88 | 88 | ||
89 | LLHost mLastSender; | 89 | LLHost mLastSender; |
90 | LLHost mLastReceivingIF; | 90 | LLHost mLastReceivingIF; |
91 | |||
92 | BOOL doSendPacket(int h_socket, const char * send_buffer, S32 buf_size, LLHost host); | ||
93 | U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE]; | ||
91 | }; | 94 | }; |
92 | 95 | ||
93 | 96 | ||
diff --git a/linden/indra/llmessage/llsocks5.cpp b/linden/indra/llmessage/llsocks5.cpp new file mode 100644 index 0000000..7326e80 --- /dev/null +++ b/linden/indra/llmessage/llsocks5.cpp | |||
@@ -0,0 +1,210 @@ | |||
1 | /** | ||
2 | * @file llsocks5.cpp | ||
3 | * @brief Socks 5 implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include <string> | ||
34 | |||
35 | #include "linden_common.h" | ||
36 | #include "net.h" | ||
37 | #include "llhost.h" | ||
38 | #include "message.h" | ||
39 | #include "llsocks5.h" | ||
40 | |||
41 | // Static class variable instances | ||
42 | |||
43 | // We want this to be static to avoid excessive indirection on every | ||
44 | // incomming packet just to do a simple bool test. The getter for this | ||
45 | // member is also static | ||
46 | bool LLSocks::sUdpProxyEnabled; | ||
47 | bool LLSocks::sHttpProxyEnabled; | ||
48 | |||
49 | LLSocks::LLSocks() | ||
50 | { | ||
51 | sUdpProxyEnabled = false; | ||
52 | sHttpProxyEnabled = false; | ||
53 | mNeedUpdate = false; | ||
54 | } | ||
55 | |||
56 | // Perform a Socks5 authentication and UDP assioacation to the proxy | ||
57 | // specified by proxy, and assiocate UDP port message_port | ||
58 | int LLSocks::proxyHandshake(LLHost proxy, U32 message_port) | ||
59 | { | ||
60 | int result; | ||
61 | |||
62 | /* Socks 5 Auth request */ | ||
63 | socks_auth_request_t socks_auth_request; | ||
64 | socks_auth_response_t socks_auth_response; | ||
65 | |||
66 | socks_auth_request.version = SOCKS_VERSION; // Socks version 5 | ||
67 | socks_auth_request.num_methods = 1; // Sending 1 method | ||
68 | socks_auth_request.methods = mAuthMethodSelected; // send only the selected metho | ||
69 | |||
70 | result = tcp_handshake(hProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request_t), (char*)&socks_auth_response, sizeof(socks_auth_response_t)); | ||
71 | if (result != 0) | ||
72 | { | ||
73 | llwarns << "Socks authentication request failed, error on TCP control channel : " << result << llendl; | ||
74 | stopProxy(); | ||
75 | return SOCKS_CONNECT_ERROR; | ||
76 | } | ||
77 | |||
78 | if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) | ||
79 | { | ||
80 | llwarns << "Socks5 server refused all our authentication methods" << llendl; | ||
81 | stopProxy(); | ||
82 | return SOCKS_NOT_ACCEPTABLE; | ||
83 | } | ||
84 | |||
85 | // SOCKS5 USERNAME/PASSWORD authentication | ||
86 | if (socks_auth_response.method == METHOD_PASSWORD) | ||
87 | { | ||
88 | // The server has requested a username/password combination | ||
89 | U32 request_size = mSocksUsername.size() + mSocksPassword.size() + 3; | ||
90 | char * password_auth = (char *)malloc(request_size); | ||
91 | password_auth[0] = 0x01; | ||
92 | password_auth[1] = mSocksUsername.size(); | ||
93 | memcpy(&password_auth[2],mSocksUsername.c_str(), mSocksUsername.size()); | ||
94 | password_auth[mSocksUsername.size()+2] = mSocksPassword.size(); | ||
95 | memcpy(&password_auth[mSocksUsername.size()+3], mSocksPassword.c_str(), mSocksPassword.size()); | ||
96 | |||
97 | authmethod_password_reply_t password_reply; | ||
98 | |||
99 | result = tcp_handshake(hProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(authmethod_password_reply_t)); | ||
100 | free (password_auth); | ||
101 | |||
102 | if (result != 0) | ||
103 | { | ||
104 | llwarns << "Socks authentication failed, error on TCP control channel : " << result << llendl; | ||
105 | stopProxy(); | ||
106 | return SOCKS_CONNECT_ERROR; | ||
107 | } | ||
108 | |||
109 | if (password_reply.status != AUTH_SUCCESS) | ||
110 | { | ||
111 | llwarns << "Socks authentication failed" << llendl; | ||
112 | stopProxy(); | ||
113 | return SOCKS_AUTH_FAIL; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* SOCKS5 connect request */ | ||
118 | |||
119 | socks_command_request_t connect_request; | ||
120 | socks_command_response_t connect_reply; | ||
121 | |||
122 | connect_request.version = SOCKS_VERSION; //Socks V5 | ||
123 | connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP | ||
124 | connect_request.flag = FIELD_RESERVED; | ||
125 | connect_request.atype = ADDRESS_IPV4; | ||
126 | connect_request.address = 0; // 0.0.0.0 We are not fussy about address | ||
127 | // UDP is promiscious receive for our protocol | ||
128 | connect_request.port = 0; // Port must be 0 if you ever want to connect via NAT and your router does port rewrite for you | ||
129 | |||
130 | result = tcp_handshake(hProxyControlChannel, (char*)&connect_request, sizeof(socks_command_request_t), (char*)&connect_reply, sizeof(socks_command_response_t)); | ||
131 | if (result != 0) | ||
132 | { | ||
133 | llwarns << "Socks connect request failed, error on TCP control channel : " << result << llendl; | ||
134 | stopProxy(); | ||
135 | return SOCKS_CONNECT_ERROR; | ||
136 | } | ||
137 | |||
138 | if (connect_reply.reply != REPLY_REQUEST_GRANTED) | ||
139 | { | ||
140 | //Something went wrong | ||
141 | llwarns << "Connection to SOCKS5 server failed, UDP forward request not granted" << llendl; | ||
142 | stopProxy(); | ||
143 | return SOCKS_UDP_FWD_NOT_GRANTED; | ||
144 | } | ||
145 | |||
146 | mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order | ||
147 | mUDPProxy.setAddress(proxy.getAddress()); | ||
148 | // All good now we have been given the UDP port to send requests that need forwarding. | ||
149 | llinfos << "Socks 5 UDP proxy connected on " << mUDPProxy << llendl; | ||
150 | return SOCKS_OK; | ||
151 | } | ||
152 | |||
153 | int LLSocks::startProxy(LLHost proxy, U32 message_port) | ||
154 | { | ||
155 | int status; | ||
156 | |||
157 | mTCPProxy = proxy; | ||
158 | mNeedUpdate = false; | ||
159 | |||
160 | stopProxy(); | ||
161 | hProxyControlChannel = tcp_open_channel(proxy); | ||
162 | if (hProxyControlChannel == -1) | ||
163 | { | ||
164 | return SOCKS_HOST_CONNECT_FAILED; | ||
165 | } | ||
166 | |||
167 | status = proxyHandshake(proxy, message_port); | ||
168 | if (status == SOCKS_OK) | ||
169 | { | ||
170 | sUdpProxyEnabled=true; | ||
171 | } | ||
172 | return status; | ||
173 | } | ||
174 | |||
175 | int LLSocks::startProxy(std::string host, U32 port) | ||
176 | { | ||
177 | mTCPProxy.setHostByName(host); | ||
178 | mTCPProxy.setPort(port); | ||
179 | return startProxy(mTCPProxy, (U32)gMessageSystem->mPort); | ||
180 | } | ||
181 | |||
182 | void LLSocks::stopProxy() | ||
183 | { | ||
184 | sUdpProxyEnabled = false; | ||
185 | |||
186 | if (hProxyControlChannel) | ||
187 | { | ||
188 | tcp_close_channel(hProxyControlChannel); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void LLSocks::setAuthNone() | ||
193 | { | ||
194 | mAuthMethodSelected = METHOD_NOAUTH; | ||
195 | } | ||
196 | |||
197 | |||
198 | void LLSocks::setAuthPassword(std::string username, std::string password) | ||
199 | { | ||
200 | mAuthMethodSelected = METHOD_PASSWORD; | ||
201 | mSocksUsername = username; | ||
202 | mSocksPassword = password; | ||
203 | } | ||
204 | |||
205 | void LLSocks::EnableHttpProxy(LLHost httpHost, LLHttpProxyType type) | ||
206 | { | ||
207 | sHttpProxyEnabled = true; | ||
208 | mHTTPProxy = httpHost; | ||
209 | mProxyType = type; | ||
210 | } | ||
diff --git a/linden/indra/llmessage/llsocks5.h b/linden/indra/llmessage/llsocks5.h new file mode 100644 index 0000000..d422d20 --- /dev/null +++ b/linden/indra/llmessage/llsocks5.h | |||
@@ -0,0 +1,248 @@ | |||
1 | /** | ||
2 | * @file llsocks5.h | ||
3 | * @brief Socks 5 implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2001&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2001-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_SOCKS5_H | ||
34 | #define LL_SOCKS5_H | ||
35 | |||
36 | #include "llhost.h" | ||
37 | #include "llmemory.h" | ||
38 | #include <string> | ||
39 | |||
40 | // Error codes returned from the StartProxy method | ||
41 | |||
42 | #define SOCKS_OK 0 | ||
43 | #define SOCKS_CONNECT_ERROR -1 | ||
44 | #define SOCKS_NOT_PERMITTED -2 | ||
45 | #define SOCKS_NOT_ACCEPTABLE -3 | ||
46 | #define SOCKS_AUTH_FAIL -4 | ||
47 | #define SOCKS_UDP_FWD_NOT_GRANTED -5 | ||
48 | #define SOCKS_HOST_CONNECT_FAILED -6 | ||
49 | |||
50 | #ifndef MAXHOSTNAMELEN | ||
51 | #define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ | ||
52 | #endif | ||
53 | |||
54 | #define SOCKS_VERSION 0x05 // we are using socks 5 | ||
55 | |||
56 | // socks 5 address/hostname types | ||
57 | #define ADDRESS_IPV4 0x01 | ||
58 | #define ADDRESS_HOSTNAME 0x03 | ||
59 | #define ADDRESS_IPV6 0x04 | ||
60 | |||
61 | // Lets just use our own ipv4 struct rather than dragging in system | ||
62 | // specific headers | ||
63 | union ipv4_address_t { | ||
64 | unsigned char octects[4]; | ||
65 | U32 addr32; | ||
66 | }; | ||
67 | |||
68 | // Socks 5 control channel commands | ||
69 | #define COMMAND_TCP_STREAM 0x01 | ||
70 | #define COMMAND_TCP_BIND 0x02 | ||
71 | #define COMMAND_UDP_ASSOCIATE 0x03 | ||
72 | |||
73 | // Socks 5 command replys | ||
74 | #define REPLY_REQUEST_GRANTED 0x00 | ||
75 | #define REPLY_GENERAL_FAIL 0x01 | ||
76 | #define REPLY_RULESET_FAIL 0x02 | ||
77 | #define REPLY_NETWORK_UNREACHABLE 0x03 | ||
78 | #define REPLY_HOST_UNREACHABLE 0x04 | ||
79 | #define REPLY_CONNECTION_REFUSED 0x05 | ||
80 | #define REPLY_TTL_EXPIRED 0x06 | ||
81 | #define REPLY_PROTOCOL_ERROR 0x07 | ||
82 | #define REPLY_TYPE_NOT_SUPPORTED 0x08 | ||
83 | |||
84 | #define FIELD_RESERVED 0x00 | ||
85 | |||
86 | // The standard socks5 request packet | ||
87 | // Push current alignment to stack and set alignment to 1 byte boundary | ||
88 | // This enabled us to use structs directly to set up and receive network packets | ||
89 | // into the correct fields, without fear of boundary alignment causing issues | ||
90 | #pragma pack(push,1) | ||
91 | |||
92 | // Socks5 command packet | ||
93 | struct socks_command_request_t { | ||
94 | unsigned char version; | ||
95 | unsigned char command; | ||
96 | unsigned char flag; | ||
97 | unsigned char atype; | ||
98 | U32 address; | ||
99 | U16 port; | ||
100 | }; | ||
101 | |||
102 | // Standard socks5 reply packet | ||
103 | struct socks_command_response_t { | ||
104 | unsigned char version; | ||
105 | unsigned char reply; | ||
106 | unsigned char flag; | ||
107 | unsigned char atype; | ||
108 | unsigned char add_bytes[4]; | ||
109 | U16 port; | ||
110 | }; | ||
111 | |||
112 | #define AUTH_NOT_ACCEPTABLE 0xFF // reply if prefered methods are not avaiable | ||
113 | #define AUTH_SUCCESS 0x00 // reply if authentication successfull | ||
114 | |||
115 | // socks 5 authentication request, stating which methods the client supports | ||
116 | struct socks_auth_request_t { | ||
117 | unsigned char version; | ||
118 | unsigned char num_methods; | ||
119 | unsigned char methods; // We are only using a single method currently | ||
120 | }; | ||
121 | |||
122 | // socks 5 authentication response packet, stating server prefered method | ||
123 | struct socks_auth_response_t { | ||
124 | unsigned char version; | ||
125 | unsigned char method; | ||
126 | }; | ||
127 | |||
128 | // socks 5 password reply packet | ||
129 | struct authmethod_password_reply_t { | ||
130 | unsigned char version; | ||
131 | unsigned char status; | ||
132 | }; | ||
133 | |||
134 | // socks 5 UDP packet header | ||
135 | struct proxywrap_t { | ||
136 | U16 rsv; | ||
137 | U8 frag; | ||
138 | U8 atype; | ||
139 | U32 addr; | ||
140 | U16 port; | ||
141 | }; | ||
142 | |||
143 | #pragma pack(pop) /* restore original alignment from stack */ | ||
144 | |||
145 | |||
146 | // Currently selected http proxy type | ||
147 | enum LLHttpProxyType | ||
148 | { | ||
149 | LLPROXY_SOCKS=0, | ||
150 | LLPROXY_HTTP=1 | ||
151 | }; | ||
152 | |||
153 | // Auth types | ||
154 | enum LLSocks5AuthType | ||
155 | { | ||
156 | METHOD_NOAUTH=0x00, // Client supports no auth | ||
157 | METHOD_GSSAPI=0x01, // Client supports GSSAPI (Not currently supported) | ||
158 | METHOD_PASSWORD=0x02 // Client supports username/password | ||
159 | }; | ||
160 | |||
161 | class LLSocks: public LLSingleton<LLSocks> | ||
162 | { | ||
163 | public: | ||
164 | LLSocks(); | ||
165 | |||
166 | // Start a connection to the socks 5 proxy | ||
167 | int startProxy(std::string host,U32 port); | ||
168 | int startProxy(LLHost proxy,U32 messagePort); | ||
169 | |||
170 | // Disconnect and clean up any connection to the socks 5 proxy | ||
171 | void stopProxy(); | ||
172 | |||
173 | // Set up to use Password auth when connecting to the socks proxy | ||
174 | void setAuthPassword(std::string username,std::string password); | ||
175 | |||
176 | // Set up to use No Auth when connecting to the socks proxy; | ||
177 | void setAuthNone(); | ||
178 | |||
179 | // get the currently selected auth method | ||
180 | LLSocks5AuthType getSelectedAuthMethod() { return mAuthMethodSelected; }; | ||
181 | |||
182 | // static check for enabled status for UDP packets | ||
183 | static bool isEnabled(){return sUdpProxyEnabled;}; | ||
184 | |||
185 | // static check for enabled status for http packets | ||
186 | static bool isHttpProxyEnabled(){return sHttpProxyEnabled;}; | ||
187 | |||
188 | // Proxy http packets via httpHost, which can be a Socks5 or a http proxy | ||
189 | // as specified in type | ||
190 | void EnableHttpProxy(LLHost httpHost,LLHttpProxyType type); | ||
191 | |||
192 | // Stop proxying http packets | ||
193 | void DisableHttpProxy() {sHttpProxyEnabled = false;}; | ||
194 | |||
195 | // get the UDP proxy address and port | ||
196 | LLHost getUDPPproxy(){return mUDPProxy;}; | ||
197 | // get the socks 5 TCP control channel address and port | ||
198 | LLHost getTCPProxy(){return mTCPProxy;}; | ||
199 | //get the http proxy address and port | ||
200 | LLHost getHTTPProxy(){return mHTTPProxy;}; | ||
201 | |||
202 | // get the currently selected http proxy type | ||
203 | LLHttpProxyType getHttpProxyType(){return mProxyType;}; | ||
204 | |||
205 | // mark that we need an update due to a settings change | ||
206 | void updated() { mNeedUpdate = true; }; | ||
207 | // report if the current settings are applied or dirty pending a startProxy | ||
208 | bool needsUpdate() { return mNeedUpdate; }; | ||
209 | |||
210 | //Get the username password in a curl compatible format | ||
211 | std::string getProxyUserPwd(){ return (mSocksUsername+":"+mSocksPassword);}; | ||
212 | |||
213 | private: | ||
214 | |||
215 | // Open a communication channel to the socks5 proxy proxy, at port messagePort | ||
216 | int proxyHandshake(LLHost proxy,U32 messagePort); | ||
217 | |||
218 | // socket handle to proxy tcp control channel | ||
219 | S32 hProxyControlChannel; | ||
220 | |||
221 | // is the UDP proxy enabled | ||
222 | static bool sUdpProxyEnabled; | ||
223 | // is the http proxy enabled | ||
224 | static bool sHttpProxyEnabled; | ||
225 | |||
226 | // Have all settings been applied | ||
227 | bool mNeedUpdate; | ||
228 | |||
229 | // currently selected http proxy type | ||
230 | LLHttpProxyType mProxyType; | ||
231 | |||
232 | // UDP proxy address and port | ||
233 | LLHost mUDPProxy; | ||
234 | // TCP Proxy control channel address and port | ||
235 | LLHost mTCPProxy; | ||
236 | // HTTP proxy address and port | ||
237 | LLHost mHTTPProxy; | ||
238 | |||
239 | // socks 5 auth method selected | ||
240 | LLSocks5AuthType mAuthMethodSelected; | ||
241 | |||
242 | // socks 5 username | ||
243 | std::string mSocksUsername; | ||
244 | // socks 5 password | ||
245 | std::string mSocksPassword; | ||
246 | }; | ||
247 | |||
248 | #endif | ||
diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp index 9a80d7b..3eda579 100644 --- a/linden/indra/llmessage/message.cpp +++ b/linden/indra/llmessage/message.cpp | |||
@@ -548,9 +548,9 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak | |||
548 | S32 acks = 0; | 548 | S32 acks = 0; |
549 | S32 true_rcv_size = 0; | 549 | S32 true_rcv_size = 0; |
550 | 550 | ||
551 | U8* buffer = mTrueReceiveBuffer; | 551 | U8* buffer = mTrueReceiveBuffer.buffer; |
552 | 552 | ||
553 | mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer); | 553 | mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer.buffer); |
554 | // If you want to dump all received packets into SecondLife.log, uncomment this | 554 | // If you want to dump all received packets into SecondLife.log, uncomment this |
555 | //dumpPacketToLog(); | 555 | //dumpPacketToLog(); |
556 | // <edit> | 556 | // <edit> |
@@ -622,7 +622,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count, bool faked_message, U8 fak | |||
622 | for(S32 i = 0; i < acks; ++i) | 622 | for(S32 i = 0; i < acks; ++i) |
623 | { | 623 | { |
624 | true_rcv_size -= sizeof(TPACKETID); | 624 | true_rcv_size -= sizeof(TPACKETID); |
625 | memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/ | 625 | memcpy(&mem_id, &buffer[true_rcv_size], /* Flawfinder: ignore*/ |
626 | sizeof(TPACKETID)); | 626 | sizeof(TPACKETID)); |
627 | packet_id = ntohl(mem_id); | 627 | packet_id = ntohl(mem_id); |
628 | //LL_INFOS("Messaging") << "got ack: " << packet_id << llendl; | 628 | //LL_INFOS("Messaging") << "got ack: " << packet_id << llendl; |
@@ -3386,7 +3386,7 @@ void LLMessageSystem::dumpPacketToLog() | |||
3386 | { | 3386 | { |
3387 | S32 offset = cur_line_pos * 3; | 3387 | S32 offset = cur_line_pos * 3; |
3388 | snprintf(line_buffer + offset, sizeof(line_buffer) - offset, | 3388 | snprintf(line_buffer + offset, sizeof(line_buffer) - offset, |
3389 | "%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */ | 3389 | "%02x ", mTrueReceiveBuffer.buffer[i]); /* Flawfinder: ignore */ |
3390 | cur_line_pos++; | 3390 | cur_line_pos++; |
3391 | if (cur_line_pos >= 16) | 3391 | if (cur_line_pos >= 16) |
3392 | { | 3392 | { |
diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h index 660cd2b..1ef15d2 100644 --- a/linden/indra/llmessage/message.h +++ b/linden/indra/llmessage/message.h | |||
@@ -66,6 +66,7 @@ | |||
66 | #include "llmessagesenderinterface.h" | 66 | #include "llmessagesenderinterface.h" |
67 | 67 | ||
68 | #include "llstoredmessage.h" | 68 | #include "llstoredmessage.h" |
69 | #include "llsocks5.h" | ||
69 | 70 | ||
70 | const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; | 71 | const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; |
71 | const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; | 72 | const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; |
@@ -774,7 +775,18 @@ private: | |||
774 | LLMessagePollInfo *mPollInfop; | 775 | LLMessagePollInfo *mPollInfop; |
775 | 776 | ||
776 | U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE]; | 777 | U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE]; |
777 | U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE]; | 778 | |
779 | // Push current alignment to stack and set alignment to 1 byte boundary | ||
780 | #pragma pack(push,1) | ||
781 | |||
782 | struct ReceiveBuffer_t | ||
783 | { | ||
784 | proxywrap_t header; | ||
785 | U8 buffer[MAX_BUFFER_SIZE]; | ||
786 | } mTrueReceiveBuffer; | ||
787 | |||
788 | #pragma pack(pop) /* restore original alignment from stack */ | ||
789 | |||
778 | S32 mTrueReceiveSize; | 790 | S32 mTrueReceiveSize; |
779 | 791 | ||
780 | // Must be valid during decode | 792 | // Must be valid during decode |
diff --git a/linden/indra/llmessage/net.cpp b/linden/indra/llmessage/net.cpp index 7166271..fa51645 100644 --- a/linden/indra/llmessage/net.cpp +++ b/linden/indra/llmessage/net.cpp | |||
@@ -56,6 +56,7 @@ | |||
56 | #include "lltimer.h" | 56 | #include "lltimer.h" |
57 | #include "indra_constants.h" | 57 | #include "indra_constants.h" |
58 | 58 | ||
59 | #include "llsocks5.h" | ||
59 | 60 | ||
60 | // Globals | 61 | // Globals |
61 | #if LL_WINDOWS | 62 | #if LL_WINDOWS |
@@ -179,7 +180,91 @@ U32 ip_string_to_u32(const char* ip_string) | |||
179 | ////////////////////////////////////////////////////////////////////////////////////////// | 180 | ////////////////////////////////////////////////////////////////////////////////////////// |
180 | 181 | ||
181 | #if LL_WINDOWS | 182 | #if LL_WINDOWS |
182 | 183 | ||
184 | int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen) | ||
185 | { | ||
186 | int result; | ||
187 | result = send(handle, dataout, outlen, 0); | ||
188 | if (result != outlen) | ||
189 | { | ||
190 | S32 err = WSAGetLastError(); | ||
191 | llwarns << "Error sending data to proxy control channel, number of bytes sent were " << result << " error code was " << err << llendl; | ||
192 | return -1; | ||
193 | } | ||
194 | |||
195 | result = recv(handle, datain, maxinlen, 0); | ||
196 | if (result != maxinlen) | ||
197 | { | ||
198 | S32 err = WSAGetLastError(); | ||
199 | llwarns << "Error receiving data from proxy control channel, number of bytes received were " << result << " error code was " << err << llendl; | ||
200 | return -1; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | S32 tcp_open_channel(LLHost host) | ||
207 | { | ||
208 | // Open a TCP channel | ||
209 | // Jump through some hoops to ensure that if the request hosts is down | ||
210 | // or not reachable connect() does not block | ||
211 | |||
212 | S32 handle; | ||
213 | handle = socket(AF_INET, SOCK_STREAM, 0); | ||
214 | if (!handle) | ||
215 | { | ||
216 | llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl; | ||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | struct sockaddr_in address; | ||
221 | address.sin_port = htons(host.getPort()); | ||
222 | address.sin_family = AF_INET; | ||
223 | address.sin_addr.s_addr = host.getAddress(); | ||
224 | |||
225 | // Non blocking | ||
226 | WSAEVENT hEvent=WSACreateEvent(); | ||
227 | WSAEventSelect(handle, hEvent, FD_CONNECT) ; | ||
228 | connect(handle, (struct sockaddr*)&address, sizeof(address)) ; | ||
229 | // Wait fot 5 seconds, if we can't get a TCP channel open in this | ||
230 | // time frame then there is something badly wrong. | ||
231 | WaitForSingleObject(hEvent, 1000*5); // 5 seconds time out | ||
232 | |||
233 | WSANETWORKEVENTS netevents; | ||
234 | WSAEnumNetworkEvents(handle,hEvent,&netevents); | ||
235 | |||
236 | // Check the async event status to see if we connected | ||
237 | if ((netevents.lNetworkEvents & FD_CONNECT) == FD_CONNECT) | ||
238 | { | ||
239 | if (netevents.iErrorCode[FD_CONNECT_BIT] != 0) | ||
240 | { | ||
241 | llwarns << "Unable to open TCP channel, WSA returned an error code of " << netevents.iErrorCode[FD_CONNECT_BIT] << llendl; | ||
242 | WSACloseEvent(hEvent); | ||
243 | return -1; | ||
244 | } | ||
245 | |||
246 | // Now we are connected disable non blocking | ||
247 | // we don't need support an async interface as | ||
248 | // currently our only consumer (socks5) will make one round | ||
249 | // of packets then just hold the connection open | ||
250 | WSAEventSelect(handle, hEvent, NULL) ; | ||
251 | unsigned long NonBlock = 0; | ||
252 | ioctlsocket(handle, FIONBIO, &NonBlock); | ||
253 | |||
254 | return handle; | ||
255 | } | ||
256 | |||
257 | llwarns << "Unable to open TCP channel, Timeout is the host up?" << netevents.iErrorCode[FD_CONNECT_BIT] << llendl; | ||
258 | return -1; | ||
259 | } | ||
260 | |||
261 | void tcp_close_channel(S32 handle) | ||
262 | { | ||
263 | llinfos << "Closing TCP channel" << llendl; | ||
264 | shutdown(handle, SD_BOTH); | ||
265 | closesocket(handle); | ||
266 | } | ||
267 | |||
183 | S32 start_net(S32& socket_out, int& nPort) | 268 | S32 start_net(S32& socket_out, int& nPort) |
184 | { | 269 | { |
185 | // Create socket, make non-blocking | 270 | // Create socket, make non-blocking |
@@ -377,6 +462,77 @@ BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, i | |||
377 | 462 | ||
378 | #else | 463 | #else |
379 | 464 | ||
465 | |||
466 | int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen) | ||
467 | { | ||
468 | if (send(handle, dataout, outlen, 0) != outlen) | ||
469 | { | ||
470 | llwarns << "Error sending data to proxy control channel" << llendl; | ||
471 | return -1; | ||
472 | } | ||
473 | |||
474 | if (recv(handle, datain, maxinlen, 0) != maxinlen) | ||
475 | { | ||
476 | llwarns << "Error receiving data to proxy control channel" << llendl; | ||
477 | return -1; | ||
478 | } | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | S32 tcp_open_channel(LLHost host) | ||
484 | { | ||
485 | S32 handle; | ||
486 | handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | ||
487 | if (!handle) | ||
488 | { | ||
489 | llwarns << "Error opening TCP control socket, socket() returned " << handle << llendl; | ||
490 | return -1; | ||
491 | } | ||
492 | |||
493 | struct sockaddr_in address; | ||
494 | address.sin_port = htons(host.getPort()); | ||
495 | address.sin_family = AF_INET; | ||
496 | address.sin_addr.s_addr = host.getAddress(); | ||
497 | |||
498 | // Set the socket to non blocking for the connect() | ||
499 | int flags = fcntl(handle, F_GETFL, 0); | ||
500 | fcntl(handle, F_SETFL, flags | O_NONBLOCK); | ||
501 | |||
502 | S32 error = connect(handle, (sockaddr*)&address, sizeof(address)); | ||
503 | if (error && (errno != EINPROGRESS)) | ||
504 | { | ||
505 | llwarns << "Unable to open TCP channel, error code: " << errno << llendl; | ||
506 | return -1; | ||
507 | } | ||
508 | |||
509 | struct timeval timeout; | ||
510 | timeout.tv_sec = 5; // Maximum time to wait for the connect() to complete | ||
511 | timeout.tv_usec = 0; | ||
512 | fd_set fds; | ||
513 | FD_ZERO(&fds); | ||
514 | FD_SET(handle, &fds); | ||
515 | |||
516 | // See if we have connectde or time out after 5 seconds | ||
517 | U32 rc = select(sizeof(fds)*8, NULL, &fds, NULL, &timeout); | ||
518 | |||
519 | if (rc != 1) // we require exactly one descriptor to be set | ||
520 | { | ||
521 | llwarns << "Unable to open TCP channel" << llendl; | ||
522 | return -1; | ||
523 | } | ||
524 | |||
525 | // Return the socket to blocking operations | ||
526 | fcntl(handle, F_SETFL, flags); | ||
527 | |||
528 | return handle; | ||
529 | } | ||
530 | |||
531 | void tcp_close_channel(S32 handle) | ||
532 | { | ||
533 | close(handle); | ||
534 | } | ||
535 | |||
380 | // Create socket, make non-blocking | 536 | // Create socket, make non-blocking |
381 | S32 start_net(S32& socket_out, int& nPort) | 537 | S32 start_net(S32& socket_out, int& nPort) |
382 | { | 538 | { |
diff --git a/linden/indra/llmessage/net.h b/linden/indra/llmessage/net.h index 45b07a0..531b5c3 100644 --- a/linden/indra/llmessage/net.h +++ b/linden/indra/llmessage/net.h | |||
@@ -64,6 +64,9 @@ U32 ip_string_to_u32(const char* ip_string); // Wrapper for inet_addr() | |||
64 | 64 | ||
65 | extern const char* LOOPBACK_ADDRESS_STRING; | 65 | extern const char* LOOPBACK_ADDRESS_STRING; |
66 | 66 | ||
67 | void tcp_close_channel(S32 handle); | ||
68 | S32 tcp_open_channel(LLHost host); | ||
69 | int tcp_handshake(S32 handle, char * dataout, int outlen, char * datain, int maxinlen); | ||
67 | 70 | ||
68 | // useful MTU consts | 71 | // useful MTU consts |
69 | 72 | ||