00001
00032 #include "linden_common.h"
00033
00034 #include "net.h"
00035
00036
00037 #include <stdexcept>
00038
00039 #if LL_WINDOWS
00040 #define WIN32_LEAN_AND_MEAN
00041 #include <winsock2.h>
00042 #include <windows.h>
00043 #else
00044 #include <sys/types.h>
00045 #include <sys/socket.h>
00046 #include <netinet/in.h>
00047 #include <arpa/inet.h>
00048 #include <fcntl.h>
00049 #include <errno.h>
00050 #endif
00051
00052
00053 #include "network.h"
00054 #include "llerror.h"
00055 #include "llhost.h"
00056 #include "lltimer.h"
00057 #include "indra_constants.h"
00058
00059
00060
00061 #if LL_WINDOWS
00062
00063 SOCKADDR_IN stDstAddr;
00064 SOCKADDR_IN stSrcAddr;
00065 SOCKADDR_IN stLclAddr;
00066 static WSADATA stWSAData;
00067
00068 #else
00069
00070 struct sockaddr_in stDstAddr;
00071 struct sockaddr_in stSrcAddr;
00072 struct sockaddr_in stLclAddr;
00073
00074 #if LL_DARWIN
00075 #ifndef _SOCKLEN_T
00076 #define _SOCKLEN_T
00077 typedef int socklen_t;
00078 #endif
00079 #endif
00080
00081 #endif
00082
00083
00084 const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
00085
00086 #if LL_DARWIN
00087
00088 const int SEND_BUFFER_SIZE = 200000;
00089 const int RECEIVE_BUFFER_SIZE = 200000;
00090 #else // LL_DARWIN
00091 const int SEND_BUFFER_SIZE = 400000;
00092 const int RECEIVE_BUFFER_SIZE = 400000;
00093 #endif // LL_DARWIN
00094
00095
00096
00097 LLHost get_sender()
00098 {
00099 return LLHost(stSrcAddr.sin_addr.s_addr, ntohs(stSrcAddr.sin_port));
00100 }
00101
00102 U32 get_sender_ip(void)
00103 {
00104 return stSrcAddr.sin_addr.s_addr;
00105 }
00106
00107 U32 get_sender_port()
00108 {
00109 return ntohs(stSrcAddr.sin_port);
00110 }
00111
00112 const char* u32_to_ip_string(U32 ip)
00113 {
00114 static char buffer[MAXADDRSTR];
00115
00116
00117 in_addr in;
00118 in.s_addr = ip;
00119 char* result = inet_ntoa(in);
00120
00121
00122 if (result != NULL)
00123 {
00124 strncpy( buffer, result, MAXADDRSTR );
00125 buffer[MAXADDRSTR-1] = '\0';
00126 return buffer;
00127 }
00128 else
00129 {
00130 return "(bad IP addr)";
00131 }
00132 }
00133
00134
00135
00136 char *u32_to_ip_string(U32 ip, char *ip_string)
00137 {
00138 char *result;
00139 in_addr in;
00140
00141
00142 in.s_addr = ip;
00143 result = inet_ntoa(in);
00144
00145
00146 if (result != NULL)
00147 {
00148
00149 strcpy(ip_string, result);
00150 return ip_string;
00151 }
00152 else
00153 {
00154 return NULL;
00155 }
00156 }
00157
00158
00159
00160 U32 ip_string_to_u32(const char* ip_string)
00161 {
00162 return inet_addr(ip_string);
00163 }
00164
00165
00167
00169
00170 #if LL_WINDOWS
00171
00172 S32 start_net(S32& socket_out, int& nPort)
00173 {
00174
00175
00176 int nRet;
00177 int hSocket;
00178
00179 int snd_size = SEND_BUFFER_SIZE;
00180 int rec_size = RECEIVE_BUFFER_SIZE;
00181 int buff_size = 4;
00182
00183
00184 if(WSAStartup(0x0202, &stWSAData))
00185 {
00186 S32 err = WSAGetLastError();
00187 WSACleanup();
00188 llwarns << "Windows Sockets initialization failed, err " << err << llendl;
00189 return 1;
00190 }
00191
00192
00193 hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
00194 if (hSocket == INVALID_SOCKET)
00195 {
00196 S32 err = WSAGetLastError();
00197 WSACleanup();
00198 llwarns << "socket() failed, err " << err << llendl;
00199 return 2;
00200 }
00201
00202
00203 stLclAddr.sin_family = AF_INET;
00204 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00205 stLclAddr.sin_port = htons(nPort);
00206
00207 S32 attempt_port = nPort;
00208 llinfos << "attempting to connect on port " << attempt_port << llendl;
00209 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
00210
00211 if (nRet == SOCKET_ERROR)
00212 {
00213
00214 if (WSAGetLastError() == WSAEADDRINUSE)
00215 {
00216
00217 for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
00218 attempt_port <= PORT_DISCOVERY_RANGE_MAX;
00219 attempt_port++)
00220 {
00221 stLclAddr.sin_port = htons(attempt_port);
00222 llinfos << "trying port " << attempt_port << llendl;
00223 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
00224
00225 if (!(nRet == SOCKET_ERROR &&
00226 WSAGetLastError() == WSAEADDRINUSE))
00227 {
00228 break;
00229 }
00230 }
00231
00232 if (nRet == SOCKET_ERROR)
00233 {
00234 llwarns << "startNet() : Couldn't find available network port." << llendl;
00235
00236 return 3;
00237 }
00238 }
00239 else
00240
00241 {
00242 llwarns << llformat("bind() port: %d failed, Err: %d\n", nPort, WSAGetLastError()) << llendl;
00243
00244 return 4;
00245 }
00246 }
00247
00248 sockaddr_in socket_address;
00249 S32 socket_address_size = sizeof(socket_address);
00250 getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size);
00251 attempt_port = ntohs(socket_address.sin_port);
00252
00253 llinfos << "connected on port " << attempt_port << llendl;
00254 nPort = attempt_port;
00255
00256
00257 unsigned long argp = 1;
00258 nRet = ioctlsocket (hSocket, FIONBIO, &argp);
00259 if (nRet == SOCKET_ERROR)
00260 {
00261 printf("Failed to set socket non-blocking, Err: %d\n",
00262 WSAGetLastError());
00263 }
00264
00265
00266 nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
00267 if (nRet)
00268 {
00269 llinfos << "Can't set receive buffer size!" << llendl;
00270 }
00271
00272 nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
00273 if (nRet)
00274 {
00275 llinfos << "Can't set send buffer size!" << llendl;
00276 }
00277
00278 getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
00279 getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
00280
00281 llinfos << "startNet - receive buffer size : " << rec_size << llendl;
00282 llinfos << "startNet - send buffer size : " << snd_size << llendl;
00283
00284
00285 char achMCAddr[MAXADDRSTR] = " ";
00286 stDstAddr.sin_family = AF_INET;
00287 stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr);
00288 stDstAddr.sin_port = htons(nPort);
00289
00290 socket_out = hSocket;
00291 return 0;
00292 }
00293
00294 void end_net(S32& socket_out)
00295 {
00296 if (socket_out >= 0)
00297 {
00298 shutdown(socket_out, SD_BOTH);
00299 closesocket(socket_out);
00300 }
00301 WSACleanup();
00302 }
00303
00304 S32 receive_packet(int hSocket, char * receiveBuffer)
00305 {
00306
00307
00308
00309 int nRet;
00310 int addr_size = sizeof(struct sockaddr_in);
00311
00312 nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size);
00313 if (nRet == SOCKET_ERROR )
00314 {
00315 if (WSAEWOULDBLOCK == WSAGetLastError())
00316 return 0;
00317 if (WSAECONNRESET == WSAGetLastError())
00318 return 0;
00319 llinfos << "receivePacket() failed, Error: " << WSAGetLastError() << llendl;
00320 }
00321
00322 return nRet;
00323 }
00324
00325
00326 BOOL send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort)
00327 {
00328
00329
00330 int nRet = 0;
00331 U32 last_error = 0;
00332
00333 stDstAddr.sin_addr.s_addr = recipient;
00334 stDstAddr.sin_port = htons(nPort);
00335 do
00336 {
00337 nRet = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
00338
00339 if (nRet == SOCKET_ERROR )
00340 {
00341 last_error = WSAGetLastError();
00342 if (last_error != WSAEWOULDBLOCK)
00343 {
00344
00345
00346
00347
00348
00349 if (WSAECONNRESET == WSAGetLastError())
00350 {
00351 return TRUE;
00352 }
00353 llinfos << "sendto() failed to " << u32_to_ip_string(recipient) << ":" << nPort
00354 << ", Error " << last_error << llendl;
00355 }
00356 }
00357 } while ( (nRet == SOCKET_ERROR)
00358 &&(last_error == WSAEWOULDBLOCK));
00359
00360 return (nRet != SOCKET_ERROR);
00361 }
00362
00364
00366
00367 #else
00368
00369
00370 S32 start_net(S32& socket_out, int& nPort)
00371 {
00372 int hSocket, nRet;
00373 int snd_size = SEND_BUFFER_SIZE;
00374 int rec_size = RECEIVE_BUFFER_SIZE;
00375
00376 socklen_t buff_size = 4;
00377
00378
00379 hSocket = socket(AF_INET, SOCK_DGRAM, 0);
00380 if (hSocket < 0)
00381 {
00382 llwarns << "socket() failed" << llendl;
00383 return 1;
00384 }
00385
00386
00387
00388 if (NET_USE_OS_ASSIGNED_PORT == nPort)
00389 {
00390
00391 }
00392 else
00393 {
00394
00395 stLclAddr.sin_family = AF_INET;
00396 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00397 stLclAddr.sin_port = htons(nPort);
00398 U32 attempt_port = nPort;
00399 llinfos << "attempting to connect on port " << attempt_port << llendl;
00400
00401 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
00402 if (nRet < 0)
00403 {
00404
00405 if (errno == EADDRINUSE)
00406 {
00407
00408 for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
00409 attempt_port <= PORT_DISCOVERY_RANGE_MAX;
00410 attempt_port++)
00411 {
00412 stLclAddr.sin_port = htons(attempt_port);
00413 llinfos << "trying port " << attempt_port << llendl;
00414 nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
00415 if (!((nRet < 0) && (errno == EADDRINUSE)))
00416 {
00417 break;
00418 }
00419 }
00420 if (nRet < 0)
00421 {
00422 llwarns << "startNet() : Couldn't find available network port." << llendl;
00423
00424 return 3;
00425 }
00426 }
00427
00428 else
00429 {
00430 llwarns << llformat ("bind() port: %d failed, Err: %s\n", nPort, strerror(errno)) << llendl;
00431
00432 return 4;
00433 }
00434 }
00435 llinfos << "connected on port " << attempt_port << llendl;
00436 nPort = attempt_port;
00437 }
00438
00439 fcntl(hSocket, F_SETFL, O_NONBLOCK);
00440
00441 nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
00442 if (nRet)
00443 {
00444 llinfos << "Can't set receive size!" << llendl;
00445 }
00446 nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
00447 if (nRet)
00448 {
00449 llinfos << "Can't set send size!" << llendl;
00450 }
00451 getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
00452 getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
00453
00454 llinfos << "startNet - receive buffer size : " << rec_size << llendl;
00455 llinfos << "startNet - send buffer size : " << snd_size << llendl;
00456
00457
00458 char achMCAddr[MAXADDRSTR] = "127.0.0.1";
00459 stDstAddr.sin_family = AF_INET;
00460 stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr);
00461 stDstAddr.sin_port = htons(nPort);
00462
00463 socket_out = hSocket;
00464 return 0;
00465 }
00466
00467 void end_net(S32& socket_out)
00468 {
00469 if (socket_out >= 0)
00470 {
00471 close(socket_out);
00472 }
00473 }
00474
00475 int receive_packet(int hSocket, char * receiveBuffer)
00476 {
00477
00478
00479
00480
00481 int nRet;
00482 socklen_t addr_size = sizeof(struct sockaddr_in);
00483
00484 nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size);
00485
00486 if (nRet == -1)
00487 {
00488
00489 return 0;
00490 }
00491
00492 return nRet;
00493 }
00494
00495 BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient, int nPort)
00496 {
00497 int ret;
00498 BOOL success;
00499 BOOL resend;
00500 S32 send_attempts = 0;
00501
00502 stDstAddr.sin_addr.s_addr = recipient;
00503 stDstAddr.sin_port = htons(nPort);
00504
00505 do
00506 {
00507 ret = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
00508 send_attempts++;
00509
00510 if (ret >= 0)
00511 {
00512
00513 success = TRUE;
00514 resend = FALSE;
00515 }
00516 else
00517 {
00518
00519 success = FALSE;
00520
00521 if (errno == EAGAIN)
00522 {
00523
00524 llinfos << "sendto() reported buffer full, resending (attempt " << send_attempts << ")" << llendl;
00525 llinfos << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << llendl;
00526 resend = TRUE;
00527 }
00528 else if (errno == ECONNREFUSED)
00529 {
00530
00531 llinfos << "sendto() reported connection refused, resending (attempt " << send_attempts << ")" << llendl;
00532 llinfos << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << llendl;
00533 resend = TRUE;
00534 }
00535 else
00536 {
00537
00538 llinfos << "sendto() failed: " << errno << ", " << strerror(errno) << llendl;
00539 llinfos << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << llendl;
00540 resend = FALSE;
00541 }
00542 }
00543 }
00544 while ( resend && send_attempts < 3);
00545
00546 if (send_attempts >= 3)
00547 {
00548 llinfos << "sendPacket() bailed out of send!" << llendl;
00549 return FALSE;
00550 }
00551
00552 return success;
00553 }
00554
00555 #endif
00556
00557