00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "udpraw.h"
00020 #include <algorithm>
00021 #include <ctime>
00022 #include <iostream>
00023 #include <string>
00024 #ifndef _MSC_VER
00025 #include <sys/time.h>
00026 #include <stdio.h>
00027 #include <sys/errno.h>
00028 #include <arpa/inet.h>
00029
00030
00031 #endif
00032
00033 #ifdef max
00034 #undef max // get rid of annoying windows definitions that override std::max()
00035 #endif
00036 #ifdef min
00037 #undef min
00038 #endif
00039
00040 Udpraw::Udpraw()
00041 {
00042 createdRecv = false;
00043 createdSend = false;
00044 FD_ZERO(&readSocks);
00045 FD_ZERO(&writeSocks);
00046 FD_ZERO(&exceptionSocks);
00047 recvSocket = 0;
00048 sendSocket = 0;
00049
00050
00051 statSent = 0;
00052 statRecvd = 0;
00053 lastError = UDPRAW_NO_ERROR;
00054 errorPrepend = "Udpraw error: ";
00055
00056 simulateLoss.send = 0.0;
00057 simulateLoss.recv = 0.0;
00058 srand(time(NULL));
00059
00060 #ifdef _MSC_VER
00061 initWSA = false;
00062 #endif
00063 }
00064
00065 Udpraw::~Udpraw()
00066 {
00067 closeAndCleanup();
00068 }
00069
00070 int Udpraw::getError()
00071
00072 {
00073 int temp = lastError;
00074 lastError = UDPRAW_NO_ERROR;
00075 return temp;
00076 }
00077
00078 std::string Udpraw::getErrorStr()
00079
00080 {
00081 return getErrorStr(getError());
00082 }
00083
00084 std::string Udpraw::getErrorStr(int error)
00085
00086 {
00087 std::string str;
00088
00089 switch (error)
00090 {
00091 case UDPRAW_NO_ERROR:
00092 str = "No error.";
00093 break;
00094 case UDPRAW_BIND:
00095 str = "Error binding.";
00096 break;
00097 case UDPRAW_MSGSIZE:
00098 str = "Buffer not big enough for message, some data lost.";
00099 break;
00100 case UDPRAW_NOINIT:
00101 str = "Socket not initialised.";
00102 break;
00103 case UDPRAW_NOIP:
00104 str = "No ip address specified.";
00105 break;
00106 case UDPRAW_NOPORT:
00107 str = "No port specified.";
00108 break;
00109 case UDPRAW_RECV:
00110 str = "Error receiving (not message size).";
00111 break;
00112 case UDPRAW_SELECT:
00113 str = "Error with select.";
00114 break;
00115 case UDPRAW_SEND:
00116 str = "Error sending.";
00117 break;
00118 case UDPRAW_SOCKEXCEPTION:
00119 str = "Select detected a socket exception.";
00120 break;
00121 case UDPRAW_UNMATCHED:
00122 str = "> 1 IPs, > 1 ports, but the number of IPs does not match the number of ports.";
00123 break;
00124 default:
00125 str = "Error not found";
00126 break;
00127 }
00128
00129 return str;
00130 }
00131
00132 void Udpraw::writeError()
00133
00134 {
00135 std::cerr << errorPrepend;
00136 writeError(getError());
00137 }
00138
00139 void Udpraw::writeError(std::string prependMsg)
00140 {
00141 if (prependMsg != "") std::cerr << prependMsg;
00142 writeError(getError());
00143 }
00144
00145 void Udpraw::writeError(int error)
00146
00147 {
00148 std::cerr << getErrorStr(error) << std::endl;
00149 }
00150
00151 void Udpraw::init()
00152 {
00153 #ifdef _MSC_VER
00154
00155 WSAStartup(MAKEWORD(2,2), &wsaData);
00156 initWSA = true;
00157 #endif
00158 }
00159
00160 int Udpraw::initReceiver(int port)
00161
00162 {
00163 #ifdef _MSC_VER
00164 if (!initWSA) init();
00165 #endif
00166
00167
00168
00169
00170 recvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00171 createdRecv = true;
00172
00173
00174 recvAddr.sin_family = AF_INET;
00175 recvAddr.sin_port = htons(port);
00176 recvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00177
00178 #ifdef _MSC_VER
00179 if (bind(recvSocket, (SOCKADDR *) &recvAddr, sizeof(recvAddr)) != 0) {
00180 #else
00181 if (bind(recvSocket, (struct sockaddr *) &recvAddr, sizeof(recvAddr)) != 0) {
00182 #endif
00183
00184 lastError = UDPRAW_BIND;
00185 return -1;
00186 }
00187
00188 return 0;
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 }
00210
00211 void Udpraw::initSender(int port)
00212 {
00213 #ifdef _MSC_VER
00214 if (!initWSA) init();
00215 #endif
00216
00217
00218
00219
00220 sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00221
00222 sendAddr.sin_family = AF_INET;
00223
00224
00225 if (port > 0) setSendPort(port);
00226
00227 createdSend = true;
00228 }
00229
00230 void Udpraw::initSender(const char *ip, int port)
00231 {
00232 setSendIp(ip);
00233 initSender(port);
00234 }
00235
00236 void Udpraw::initSender(std::vector <std::string> ip_list, int port)
00237 {
00238 setSendIp(ip_list);
00239 initSender(port);
00240 }
00241
00242 void Udpraw::initSender(std::vector <std::string> ip_list, std::vector <int> port_list)
00243 {
00244 setSendIp(ip_list);
00245 initSender(0);
00246 setSendPort(port_list);
00247 }
00248
00249 void Udpraw::setSendIp(const char* ip)
00250 {
00251 sendIp.clear();
00252 sendIp.push_back(ip);
00253 }
00254
00255 void Udpraw::setSendIp(std::vector <std::string> ip_list)
00256 {
00257 sendIp = ip_list;
00258 }
00259
00260 void Udpraw::setSendPort(int port)
00261 {
00262 sendPort.clear();
00263 sendPort.push_back(port);
00264 }
00265
00266 void Udpraw::setSendPort(std::vector <int> port_list)
00267 {
00268 sendPort = port_list;
00269 }
00270
00271 int Udpraw::doSelect()
00272
00273
00274
00275 {
00276 struct timeval timeout;
00277 timeout.tv_sec = 0;
00278 timeout.tv_usec = 0;
00279
00280 FD_ZERO(&readSocks);
00281 FD_ZERO(&writeSocks);
00282 FD_ZERO(&exceptionSocks);
00283
00284 if (createdRecv) {
00285 FD_SET(recvSocket, &readSocks);
00286 FD_SET(recvSocket, &exceptionSocks);
00287 }
00288 if (createdSend) {
00289 FD_SET(sendSocket, &writeSocks);
00290 FD_SET(sendSocket, &exceptionSocks);
00291 }
00292
00293 int sockfdMax = std::max( (int) recvSocket, (int) sendSocket ) + 1;
00294
00295
00296 if ((numSocksReadable = select(sockfdMax, &readSocks, &writeSocks, &exceptionSocks, &timeout)) == -1) {
00297 lastError = UDPRAW_SELECT;
00298 return -1;
00299 }
00300
00301 if (FD_ISSET(recvSocket, &exceptionSocks) || FD_ISSET(sendSocket, &exceptionSocks)) {
00302 lastError = UDPRAW_SOCKEXCEPTION;
00303 return -2;
00304 }
00305
00306 return 0;
00307 }
00308
00309 int Udpraw::recvRaw(char* buf, int len, bool select)
00310
00311
00312
00313 {
00314
00315 if (!createdRecv) {
00316 lastError = UDPRAW_NOINIT;
00317 return -2;
00318 }
00319
00320 if (!select || FD_ISSET(recvSocket, &readSocks)) {
00321 #ifdef _MSC_VER
00322 int fromAddrSize = sizeof(fromAddr);
00323 #else
00324 socklen_t fromAddrSize = sizeof(fromAddr);
00325 #endif
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 #ifdef _MSC_VER
00337 int bytesRecvd = recvfrom(recvSocket, buf, len, 0, (SOCKADDR *)&fromAddr, &fromAddrSize);
00338 #else
00339 int bytesRecvd = recvfrom(recvSocket, buf, len, 0, (struct sockaddr *)&fromAddr, &fromAddrSize);
00340 #endif
00341
00342 if (bytesRecvd > 0) statRecvd += bytesRecvd;
00343
00344 #ifdef _MSC_VER
00345 if (bytesRecvd == 0 || bytesRecvd == SOCKET_ERROR)
00346 #else
00347 if (bytesRecvd < 1)
00348 #endif
00349 {
00350
00351 #ifdef _MSC_VER
00352 int error = WSAGetLastError();
00353 if (error == WSAEMSGSIZE) {
00354
00355
00356 lastError = UDPRAW_MSGSIZE;
00357 return -1;
00358 }else{
00359 lastError = UDPRAW_RECV;
00360 return -2;
00361 }
00362 #else
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 lastError = UDPRAW_RECV;
00391 return -2;
00392 #endif
00393 }
00394
00395
00396 if (simulateLoss.recv > 0.0 && simulatePacketLoss(simulateLoss.recv)) return 0;
00397
00398 return bytesRecvd;
00399 }else{
00400 return 0;
00401 }
00402 }
00403
00404 int Udpraw::sendRaw(const char* buf, int len, bool select)
00405
00406
00407 {
00408 int minbytes = -1, bytes = 0;
00409
00410 std::vector<std::string>::iterator ip_iterator = sendIp.begin();
00411 std::vector<int>::iterator port_iterator = sendPort.begin();
00412
00413 if (!createdSend) {
00414 lastError = UDPRAW_NOINIT;
00415 return -1;
00416 }
00417
00418
00419
00420 if (sendPort.size() == 0) {
00421
00422 lastError = UDPRAW_NOPORT;
00423 return -1;
00424 }
00425 if (sendIp.size() == 0) {
00426
00427 lastError = UDPRAW_NOIP;
00428 return -1;
00429 }
00430 if (sendPort.size() > 1 && sendIp.size() > 1) {
00431
00432 if (sendPort.size() != sendIp.size()) {
00433
00434 lastError = UDPRAW_UNMATCHED;
00435 return -1;
00436 }
00437 }
00438
00439
00440
00441 if (simulateLoss.send > 0.0 && simulatePacketLoss(simulateLoss.send)) return 0;
00442
00443
00444 bool first = true;
00445 while (ip_iterator != sendIp.end() && port_iterator != sendPort.end())
00446 {
00447 if (first) first = false;
00448 else{
00449 if (select) doSelect();
00450
00451 }
00452 if (!select || FD_ISSET(sendSocket, &writeSocks)) {
00453 sendAddr.sin_port = htons(*port_iterator);
00454 sendAddr.sin_addr.s_addr = inet_addr(ip_iterator->c_str());
00455
00456 #ifdef _MSC_VER
00457 bytes = sendto(sendSocket, buf, len, 0, (SOCKADDR *) &sendAddr, sizeof(sendAddr));
00458 if (bytes == SOCKET_ERROR) bytes = -1;
00459 #else
00460 bytes = sendto(sendSocket, buf, len, 0, (struct sockaddr *) &sendAddr, sizeof(sendAddr));
00461
00462 #endif
00463 if (bytes == -1) lastError = UDPRAW_SEND;
00464 if (bytes > 0) statSent += bytes;
00465 if (minbytes < 0 || bytes < minbytes) minbytes = bytes;
00466 }else break;
00467
00468
00469 if (sendIp.size() > 1) ++ip_iterator;
00470 if (sendPort.size() > 1) ++port_iterator;
00471 if (sendIp.size() == 1 && sendPort.size() == 1) break;
00472 }
00473
00474 return minbytes;
00475 }
00476
00477 int Udpraw::getStatSent()
00478 {
00479 return statSent;
00480 }
00481
00482 int Udpraw::getStatRecvd()
00483 {
00484 return statRecvd;
00485 }
00486
00487 void Udpraw::setStatSent(int bytes)
00488 {
00489 statSent = bytes;
00490 }
00491
00492 void Udpraw::setStatRecvd(int bytes)
00493 {
00494 statRecvd = bytes;
00495 }
00496
00497 void Udpraw::setSimulateLossSend(float n)
00498 {
00499 simulateLoss.send = n;
00500 }
00501
00502 void Udpraw::setSimulateLossRecv(float n)
00503 {
00504 simulateLoss.recv = n;
00505 }
00506
00507 float Udpraw::getSimulateLossSend()
00508 {
00509 return simulateLoss.send;
00510 }
00511
00512 float Udpraw::getSimulateLossRecv()
00513 {
00514 return simulateLoss.recv;
00515 }
00516
00517 bool Udpraw::simulatePacketLoss(float prob)
00518
00519 {
00520 if (rand() % 1000 < prob * 1000) return true;
00521 return false;
00522 }
00523
00524 int Udpraw::closeAndCleanup()
00525 {
00526 int retval = 0;
00527 #ifdef _MSC_VER
00528 if (createdRecv) { createdRecv = false; if (closesocket(recvSocket) != 0) retval = 1; }
00529 if (createdSend) { createdSend = false; if (closesocket(sendSocket) != 0) retval = 1; }
00530 if (initWSA) { initWSA = false; WSACleanup(); }
00531 #else
00532 if (createdRecv) { createdRecv = false; if (close(recvSocket) != 0) retval = 1; }
00533 if (createdSend) { createdSend = false; if (close(sendSocket) != 0) retval = 1; }
00534 #endif
00535
00536 return retval;
00537 }
00538