00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "cxutils/networking/udpclient.h"
00041 #include <string.h>
00042 #include <iostream>
00043
00044 using namespace std;
00045 using namespace CxUtils;
00046
00052 UdpClient::UdpClient()
00053 {
00054 mComputer = 0;
00055 mHP = NULL;
00056 memset((void *)&mService, 0, sizeof(struct sockaddr_in));
00057 memset((void *)&mSendAddr, 0, sizeof(struct sockaddr_in));
00058 memset((void *)&mRecvAddr, 0, sizeof(struct sockaddr_in));
00059 mSocketType = UDPClient;
00060 mDestinationPort = 0;
00061 mSourcePort = 0;
00062 mDuplicateSocket = false;
00063 }
00064
00070 UdpClient::~UdpClient()
00071 {
00072 Shutdown();
00073 }
00074
00080 void UdpClient::Shutdown()
00081 {
00082 if(mDuplicateSocket == false)
00083 {
00084 if(mSocket)
00085 {
00086 #ifdef WIN32
00087 closesocket(mSocket);
00088 #else
00089 close(mSocket);
00090 #endif
00091 mSocket = 0;
00092 }
00093 Socket::Shutdown();
00094 }
00095 else
00096 {
00097 mSocket = 0;
00098 mServiceLength = 0;
00099 mGoodSocket = false;
00100 memset(&mService, 0, sizeof(struct sockaddr_in));
00101 }
00102 mDestinationPort = 0;
00103 mSourcePort = 0;
00104 mComputer = 0;
00105 mSocketType = UDPClient;
00106 memset((void *)&mService, 0, sizeof(struct sockaddr_in));
00107 memset((void *)&mSendAddr, 0, sizeof(struct sockaddr_in));
00108 memset((void *)&mRecvAddr, 0, sizeof(struct sockaddr_in));
00109 mConnectionID.Clear();
00110 }
00111
00112
00128 int UdpClient::InitializeSocket(const IP4Address& ipAddress,
00129 const unsigned short destinationPort,
00130 const unsigned short sourcePort)
00131 {
00132
00133 Shutdown();
00134
00135 memset((void *)&mService, 0, sizeof(struct sockaddr_in));
00136 memset((void *)&mSendAddr, 0, sizeof(struct sockaddr_in));
00137 memset((void *)&mRecvAddr, 0, sizeof(struct sockaddr_in));
00138
00139
00140 mSocket = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00141 mDestinationPort = destinationPort;
00142
00143 if(mSocket > 0)
00144 {
00145
00146 mRecvAddr.sin_family = AF_INET;
00147 mRecvAddr.sin_port = htons(sourcePort);
00148 mRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00149
00150 if(bind(mSocket, (struct sockaddr *) &mRecvAddr, sizeof(mRecvAddr)) >= 0)
00151 {
00152 int bufferSize = 262144;
00153 int on = 1;
00154 int options = 0;
00155
00156
00157 mSendAddr.sin_family = AF_INET;
00158 mSendAddr.sin_port = htons(mDestinationPort);
00159 if( strstr(ipAddress.mString.c_str(), "255") != 0 )
00160 {
00161 mSendAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
00162 if(setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0)
00163 {
00164 cout << "UDP ERROR: setsockopt failed SO_BROADCAST. ERRNO: " << errno << "-" << strerror(errno) << "\n";
00165 Shutdown();
00166 return 0;
00167 }
00168 }
00169 else
00170 {
00171 mHP = gethostbyname(ipAddress.mString.c_str());
00172 if(mHP == NULL)
00173 {
00174
00175 cout << "UDP ERROR: hostname lookup failure. ERRNO: " << errno << "-" << strerror(errno) << "\n";
00176 Shutdown();
00177 return 0;
00178 }
00179 mComputer = *((long *) mHP->h_addr);
00180 mSendAddr.sin_addr.s_addr = mComputer;
00181
00182 }
00183
00184 options |= setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (char *)&bufferSize, (int)sizeof(bufferSize));
00185 options |= setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, (char *)&bufferSize, (int)sizeof(bufferSize));
00186 if(options != 0)
00187 {
00188 cout << "UDP ERROR: Failed to set UDP socket options.\n";
00189 Shutdown();
00190 return 0;
00191 }
00192
00193
00194 #ifdef WIN32
00195 int length = sizeof(mRecvAddr);
00196 #else
00197 socklen_t length = sizeof(mRecvAddr);
00198 #endif
00199
00200 if(getsockname(mSocket, (struct sockaddr*)&mRecvAddr, &length) != 0)
00201 {
00202 #ifdef WIN32
00203 int errorCode = WSAGetLastError();
00204 cout << "UDP ERROR: getsockname failed. " << errorCode << "\n";
00205 #endif
00206 Shutdown();
00207 return 0;
00208 }
00209 mSourcePort = (unsigned short)ntohs(mRecvAddr.sin_port);
00210
00211
00212 mGoodSocket = true;
00213 mConnectionID = ipAddress;
00214 memcpy(&mService, &mRecvAddr, sizeof(mRecvAddr));
00215 mServiceLength = sizeof(mService);
00216 }
00217 }
00218
00219 return mGoodSocket;
00220
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00307 int UdpClient::InitializeMulticastSocket(const IP4Address& multicastGroup,
00308 const unsigned short destinationPort,
00309 const unsigned char ttl,
00310 const bool broadcastFlag,
00311 const unsigned short sourcePort,
00312 const bool allowReuse)
00313 {
00314
00315 Shutdown();
00316
00317 memset((void *)&mService, 0, sizeof(struct sockaddr_in));
00318 memset((void *)&mSendAddr, 0, sizeof(struct sockaddr_in));
00319 memset((void *)&mRecvAddr, 0, sizeof(struct sockaddr_in));
00320
00321
00322 mSocket = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00323 mDestinationPort = destinationPort;
00324
00325 if(mSocket > 0)
00326 {
00327 int bufferSize = 262144;
00328 int on = 1;
00329 struct ip_mreq mreq;
00330 int code = 0;
00331
00332
00333 mRecvAddr.sin_family = AF_INET;
00334 mRecvAddr.sin_port = htons(sourcePort);
00335 mRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00336
00337
00338 if(allowReuse == true && setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
00339 {
00340 cout << "UDP ERROR: setsockopt failed SO_REUSEADDR. ERRNO: " << errno << "-" << strerror(errno) << "\n";
00341 Shutdown();
00342 return 0;
00343 }
00344
00345
00346 if(bind(mSocket, (struct sockaddr *) &mRecvAddr, sizeof(mRecvAddr)) >= 0)
00347 {
00348
00349 mSendAddr.sin_family = AF_INET;
00350 mSendAddr.sin_port = htons(mDestinationPort);
00351
00352 if(mNetworkInterface >= 0)
00353 {
00354 IP4Address::List myHostnames;
00355 GetHostAddresses(myHostnames);
00356 if(mNetworkInterface < (int)(myHostnames.size()))
00357 {
00358 mRecvAddr.sin_addr.s_addr = *((long *)gethostbyname(myHostnames[mNetworkInterface].mString.c_str())->h_addr);
00359 mreq.imr_interface.s_addr = inet_addr(IP4Address(myHostnames[mNetworkInterface]).mString.c_str());
00360 }
00361 else
00362 {
00363 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
00364 }
00365 }
00366 else
00367 {
00368 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
00369 }
00370
00371 mreq.imr_multiaddr.s_addr = inet_addr(multicastGroup.mString.c_str());
00372
00373 if(broadcastFlag)
00374 {
00375 mSendAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
00376 setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on));
00377 }
00378 else
00379 {
00380 mHP = gethostbyname(multicastGroup.mString.c_str());
00381 if(mHP == NULL)
00382 {
00383
00384 cout << "Multicast Groupname Lookup Failure!\n";
00385 Shutdown();
00386 return 0;
00387 }
00388 mComputer = *((long *) mHP->h_addr);
00389 mSendAddr.sin_addr.s_addr = mComputer;
00390 }
00391 int options = 0;
00392 options |= setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, (char *)&bufferSize, (int)sizeof(bufferSize));
00393 options |= setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, (char *)&bufferSize, (int)sizeof(bufferSize));
00394 options |= setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, (int)sizeof(ttl));
00395 options |= setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&on, (int)sizeof(on));
00396 if(options != 0)
00397 {
00398 cout << "UDP ERROR: Failed to set UDP socket options.\n";
00399 Shutdown();
00400 return 0;
00401 }
00402 options |= setsockopt(mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
00403 if(options != 0)
00404 {
00405 cout << "UDP ERROR: Failed to set UDP Multicast options.\n";
00406 }
00407
00408 #ifdef WIN32
00409 int length = sizeof(mRecvAddr);
00410 #else
00411 socklen_t length = sizeof(mRecvAddr);
00412 #endif
00413
00414 if(getsockname(mSocket, (struct sockaddr*)&mRecvAddr, &length) != 0)
00415 {
00416 #ifdef WIN32
00417 int errorCode = WSAGetLastError();
00418 cout << "UDP ERROR: getsockname failed. " << errorCode << "\n";
00419 #endif
00420 Shutdown();
00421 return 0;
00422 }
00423 mSourcePort = (unsigned short)ntohs(mRecvAddr.sin_port);
00424
00425
00426 mGoodSocket = true;
00427 mConnectionID = multicastGroup;
00428 memcpy(&mService, &mRecvAddr, sizeof(mRecvAddr));
00429 mServiceLength = sizeof(mService);
00430 }
00431 }
00432
00433 return mGoodSocket;
00434
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 UdpClient* UdpClient::CreateNewDestination(const IP4Address& ipAddress,
00493 const unsigned short destinationPort) const
00494 {
00495 if(IsValid() == false)
00496 {
00497 return NULL;
00498 }
00499
00500 UdpClient* client = new UdpClient();
00501
00502 client->mSocket = mSocket;
00503 client->mServiceLength = mServiceLength;
00504 client->mNetworkInterface = mNetworkInterface;
00505 client->mGoodSocket = true;
00506 client->mSourcePort = mSourcePort;
00507 client->mDestinationPort = mDestinationPort;
00508 memcpy(&client->mRecvAddr, &mRecvAddr, sizeof(sockaddr_in));
00509 memcpy(&client->mService, &mService, sizeof(mService));
00510 memset((void *)&client->mSendAddr, 0, sizeof(struct sockaddr_in));
00511
00512
00513 client->mSendAddr.sin_family = AF_INET;
00514 if(destinationPort == 0)
00515 {
00516 client->mDestinationPort = mDestinationPort;
00517 }
00518 else
00519 {
00520 client->mDestinationPort = destinationPort;
00521 }
00522 client->mSendAddr.sin_port = htons(client->mDestinationPort);
00523 int on = 1;
00524 if( strstr(ipAddress.mString.c_str(), "255") != 0 )
00525 {
00526 client->mSendAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
00527 if(setsockopt(client->mSocket, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0)
00528 {
00529 cout << "UDP ERROR: setsockopt failed SO_BROADCAST. ERRNO: " << errno << "-" << strerror(errno) << "\n";
00530 delete client;
00531 return NULL;
00532 }
00533 }
00534 else
00535 {
00536 client->mHP = gethostbyname(ipAddress.mString.c_str());
00537 if(client->mHP == NULL)
00538 {
00539
00540 cout << "UDP ERROR: hostname lookup failure. ERRNO: " << errno << "-" << strerror(errno) << "\n";
00541 delete client;
00542 return NULL;
00543 }
00544 client->mComputer = *((long *) client->mHP->h_addr);
00545 client->mSendAddr.sin_addr.s_addr = client->mComputer;
00546 }
00547 client->mConnectionID = ipAddress;
00548 client->mDuplicateSocket = true;
00549 client->mGoodSocket = true;
00550
00551 return client;
00552
00553 }
00554
00555
00567 int UdpClient::SendFromBuffer(const char *buffer,
00568 const unsigned int length) const
00569 {
00570 int result = 0;
00571
00572 if(!IsValid())
00573 {
00574 return 0;
00575 }
00576
00577 result = ::sendto(mSocket,
00578 buffer,
00579 (int)(length),
00580 0,
00581 (struct sockaddr *) &mSendAddr,
00582 sizeof(struct sockaddr));
00583 if(result == -1)
00584 {
00585 result = 0;
00586 }
00587 return result;
00588 }
00589
00590
00608 int UdpClient::RecvToBuffer(char *buffer,
00609 const unsigned int length,
00610 const long int timeOutMilliseconds,
00611 IPAddress* ipAddress,
00612 unsigned short* port) const
00613 {
00614 if(!IsValid())
00615 {
00616 return 0;
00617 }
00618
00619 if(!Socket::IsIncommingData(this, timeOutMilliseconds))
00620 {
00621 return 0;
00622 }
00623
00624 int rcvd = 0;
00625
00626 sockaddr *r;
00627
00628 r = (sockaddr *)(&mRecvAddr);
00629 memset(r, 0, sizeof(struct sockaddr));
00630 int recvlen = sizeof(struct sockaddr);
00631
00632 #ifdef WIN32
00633 rcvd = recvfrom(mSocket,
00634 buffer,
00635 length,
00636 0,
00637 (struct sockaddr *)r,
00638 &recvlen);
00639 #else
00640 rcvd = recvfrom(mSocket,
00641 buffer,
00642 length,
00643 0,
00644 (struct sockaddr *)r,
00645 (socklen_t *)&recvlen);
00646 #endif
00647
00648
00649
00650 if(rcvd > 0)
00651 {
00652 if(port || ipAddress)
00653 {
00654 struct sockaddr_in in;
00655 memcpy(&in, &mRecvAddr, sizeof(struct sockaddr_in));
00656 if(ipAddress && dynamic_cast<IP4Address*>(ipAddress))
00657 {
00658 *((IP4Address*)(ipAddress)) = std::string(inet_ntoa(in.sin_addr));
00659 }
00660 if(port)
00661 {
00662 *port = (unsigned short)ntohs(in.sin_port);
00663 }
00664 }
00665 }
00666 else
00667 {
00668 rcvd = 0;
00669 }
00670
00671 return rcvd;
00672 }
00673
00674
00675
00676