00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "GroupsockHelper.hh"
00022
00023 #if defined(__WIN32__) || defined(_WIN32)
00024 #include <time.h>
00025 extern "C" int initializeWinsockIfNecessary();
00026 #else
00027 #include <stdarg.h>
00028 #include <time.h>
00029 #include <fcntl.h>
00030 #define initializeWinsockIfNecessary() 1
00031 #endif
00032 #include <stdio.h>
00033
00034
00035 netAddressBits SendingInterfaceAddr = INADDR_ANY;
00036 netAddressBits ReceivingInterfaceAddr = INADDR_ANY;
00037
00038 static void socketErr(UsageEnvironment& env, char* errorMsg) {
00039 env.setResultErrMsg(errorMsg);
00040 }
00041
00042 static int reuseFlag = 1;
00043
00044 NoReuse::NoReuse() {
00045 reuseFlag = 0;
00046 }
00047
00048 NoReuse::~NoReuse() {
00049 reuseFlag = 1;
00050 }
00051
00052 int setupDatagramSocket(UsageEnvironment& env, Port port,
00053 #ifdef IP_MULTICAST_LOOP
00054 Boolean setLoopback
00055 #else
00056 Boolean
00057 #endif
00058 ) {
00059 if (!initializeWinsockIfNecessary()) {
00060 socketErr(env, "Failed to initialize 'winsock': ");
00061 return -1;
00062 }
00063
00064 int newSocket = socket(AF_INET, SOCK_DGRAM, 0);
00065 if (newSocket < 0) {
00066 socketErr(env, "unable to create datagram socket: ");
00067 return newSocket;
00068 }
00069
00070 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00071 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00072 socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00073 closeSocket(newSocket);
00074 return -1;
00075 }
00076
00077 #if defined(__WIN32__) || defined(_WIN32)
00078
00079 #else
00080 #ifdef SO_REUSEPORT
00081 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00082 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00083 socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00084 closeSocket(newSocket);
00085 return -1;
00086 }
00087 #endif
00088
00089 #ifdef IP_MULTICAST_LOOP
00090 const u_int8_t loop = (u_int8_t)setLoopback;
00091 if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
00092 (const char*)&loop, sizeof loop) < 0) {
00093 socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: ");
00094 closeSocket(newSocket);
00095 return -1;
00096 }
00097 #endif
00098 #endif
00099
00100
00101 netAddressBits addr = INADDR_ANY;
00102 #if defined(__WIN32__) || defined(_WIN32)
00103 #else
00104 if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00105 #endif
00106 if (port.num() == 0) addr = ReceivingInterfaceAddr;
00107 MAKE_SOCKADDR_IN(name, addr, port.num());
00108 if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00109 char tmpBuffer[100];
00110 sprintf(tmpBuffer, "bind() error (port number: %d): ",
00111 ntohs(port.num()));
00112 socketErr(env, tmpBuffer);
00113 closeSocket(newSocket);
00114 return -1;
00115 }
00116 #if defined(__WIN32__) || defined(_WIN32)
00117 #else
00118 }
00119 #endif
00120
00121
00122 if (SendingInterfaceAddr != INADDR_ANY) {
00123 struct in_addr addr;
00124 addr.s_addr = SendingInterfaceAddr;
00125
00126 if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,
00127 (const char*)&addr, sizeof addr) < 0) {
00128 socketErr(env, "error setting outgoing multicast interface: ");
00129 closeSocket(newSocket);
00130 return -1;
00131 }
00132 }
00133
00134 return newSocket;
00135 }
00136
00137 Boolean makeSocketNonBlocking(int sock) {
00138 #if defined(__WIN32__) || defined(_WIN32) || defined(IMN_PIM)
00139 unsigned long arg = 1;
00140 return ioctlsocket(sock, FIONBIO, &arg) == 0;
00141 #elif defined(VXWORKS)
00142 int arg = 1;
00143 return ioctl(sock, FIONBIO, (int)&arg) == 0;
00144 #else
00145 int curFlags = fcntl(sock, F_GETFL, 0);
00146 return fcntl(sock, F_SETFL, curFlags|O_NONBLOCK) >= 0;
00147 #endif
00148 }
00149
00150 int setupStreamSocket(UsageEnvironment& env,
00151 Port port, Boolean makeNonBlocking) {
00152 if (!initializeWinsockIfNecessary()) {
00153 socketErr(env, "Failed to initialize 'winsock': ");
00154 return -1;
00155 }
00156
00157 int newSocket = socket(AF_INET, SOCK_STREAM, 0);
00158 if (newSocket < 0) {
00159 socketErr(env, "unable to create stream socket: ");
00160 return newSocket;
00161 }
00162
00163 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00164 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00165 socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00166 closeSocket(newSocket);
00167 return -1;
00168 }
00169
00170
00171
00172
00173 #ifdef REUSE_FOR_TCP
00174 #if defined(__WIN32__) || defined(_WIN32)
00175
00176 #else
00177 #ifdef SO_REUSEPORT
00178 if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00179 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00180 socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00181 closeSocket(newSocket);
00182 return -1;
00183 }
00184 #endif
00185 #endif
00186 #endif
00187
00188
00189 #if defined(__WIN32__) || defined(_WIN32)
00190 #else
00191 if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00192 #endif
00193 MAKE_SOCKADDR_IN(name, ReceivingInterfaceAddr, port.num());
00194 if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00195 char tmpBuffer[100];
00196 sprintf(tmpBuffer, "bind() error (port number: %d): ",
00197 ntohs(port.num()));
00198 socketErr(env, tmpBuffer);
00199 closeSocket(newSocket);
00200 return -1;
00201 }
00202 #if defined(__WIN32__) || defined(_WIN32)
00203 #else
00204 }
00205 #endif
00206
00207 if (makeNonBlocking) {
00208 if (!makeSocketNonBlocking(newSocket)) {
00209 socketErr(env, "failed to make non-blocking: ");
00210 closeSocket(newSocket);
00211 return -1;
00212 }
00213 }
00214
00215 return newSocket;
00216 }
00217
00218 #ifndef IMN_PIM
00219 static int blockUntilReadable(UsageEnvironment& env,
00220 int socket, struct timeval* timeout) {
00221 int result = -1;
00222 do {
00223 fd_set rd_set;
00224 FD_ZERO(&rd_set);
00225 if (socket < 0) break;
00226 FD_SET((unsigned) socket, &rd_set);
00227 const unsigned numFds = socket+1;
00228
00229 result = select(numFds, &rd_set, NULL, NULL, timeout);
00230 if (timeout != NULL && result == 0) {
00231 break;
00232 } else if (result <= 0) {
00233 #if defined(__WIN32__) || defined(_WIN32)
00234 #else
00235 if (errno == EINTR || errno == EAGAIN) continue;
00236 #endif
00237 socketErr(env, "select() error: ");
00238 break;
00239 }
00240
00241 if (!FD_ISSET(socket, &rd_set)) {
00242 socketErr(env, "select() error - !FD_ISSET");
00243 break;
00244 }
00245 } while (0);
00246
00247 return result;
00248 }
00249 #else
00250 extern int blockUntilReadable(UsageEnvironment& env,
00251 int socket, struct timeval* timeout);
00252 #endif
00253
00254 int readSocket(UsageEnvironment& env,
00255 int socket, unsigned char* buffer, unsigned bufferSize,
00256 struct sockaddr_in& fromAddress,
00257 struct timeval* timeout) {
00258 int bytesRead = -1;
00259 do {
00260 int result = blockUntilReadable(env, socket, timeout);
00261 if (timeout != NULL && result == 0) {
00262 bytesRead = 0;
00263 break;
00264 } else if (result <= 0) {
00265 break;
00266 }
00267
00268 SOCKLEN_T addressSize = sizeof fromAddress;
00269 bytesRead = recvfrom(socket, (char*)buffer, bufferSize, 0,
00270 (struct sockaddr*)&fromAddress,
00271 &addressSize);
00272 if (bytesRead < 0) {
00273
00274 int err = env.getErrno();
00275 if (err == 111
00276 #if defined(__WIN32__) || defined(_WIN32)
00277
00278
00279
00280
00281
00282
00283 || err == 0
00284 #else
00285 || err == EAGAIN
00286 #endif
00287 || err == 113 ) {
00288
00289 fromAddress.sin_addr.s_addr = 0;
00290 return 0;
00291 }
00292
00293 socketErr(env, "recvfrom() error: ");
00294 break;
00295 }
00296 } while (0);
00297
00298 return bytesRead;
00299 }
00300
00301
00302 int readSocketExact(UsageEnvironment& env,
00303 int socket, unsigned char* buffer, unsigned bufferSize,
00304 struct sockaddr_in& fromAddress,
00305 struct timeval* timeout) {
00306
00307
00308
00309
00310 int bsize = bufferSize;
00311 int bytesRead = 0;
00312 int totBytesRead =0;
00313 do {
00314 bytesRead = readSocket (env, socket, buffer + totBytesRead, bsize,
00315 fromAddress, timeout);
00316 if (bytesRead <= 0) break;
00317 totBytesRead += bytesRead;
00318 bsize -= bytesRead;
00319 } while (bsize != 0);
00320
00321 return totBytesRead;
00322 }
00323
00324 Boolean writeSocket(UsageEnvironment& env,
00325 int socket, struct in_addr address, Port port,
00326 u_int8_t ttlArg,
00327 unsigned char* buffer, unsigned bufferSize) {
00328 do {
00329 if (ttlArg != 0) {
00330
00331 #if defined(__WIN32__) || defined(_WIN32)
00332 #define TTL_TYPE int
00333 #else
00334 #define TTL_TYPE u_int8_t
00335 #endif
00336 TTL_TYPE ttl = (TTL_TYPE)ttlArg;
00337 if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,
00338 (const char*)&ttl, sizeof ttl) < 0) {
00339 socketErr(env, "setsockopt(IP_MULTICAST_TTL) error: ");
00340 break;
00341 }
00342 }
00343
00344 MAKE_SOCKADDR_IN(dest, address.s_addr, port.num());
00345 int bytesSent = sendto(socket, (char*)buffer, bufferSize, 0,
00346 (struct sockaddr*)&dest, sizeof dest);
00347 if (bytesSent != (int)bufferSize) {
00348 char tmpBuf[100];
00349 sprintf(tmpBuf, "writeSocket(%d), sendTo() error: wrote %d bytes instead of %u: ", socket, bytesSent, bufferSize);
00350 socketErr(env, tmpBuf);
00351 break;
00352 }
00353
00354 return True;
00355 } while (0);
00356
00357 return False;
00358 }
00359
00360 static unsigned getBufferSize(UsageEnvironment& env, int bufOptName,
00361 int socket) {
00362 unsigned curSize;
00363 SOCKLEN_T sizeSize = sizeof curSize;
00364 if (getsockopt(socket, SOL_SOCKET, bufOptName,
00365 (char*)&curSize, &sizeSize) < 0) {
00366 socketErr(env, "getBufferSize() error: ");
00367 return 0;
00368 }
00369
00370 return curSize;
00371 }
00372 unsigned getSendBufferSize(UsageEnvironment& env, int socket) {
00373 return getBufferSize(env, SO_SNDBUF, socket);
00374 }
00375 unsigned getReceiveBufferSize(UsageEnvironment& env, int socket) {
00376 return getBufferSize(env, SO_RCVBUF, socket);
00377 }
00378
00379 static unsigned setBufferTo(UsageEnvironment& env, int bufOptName,
00380 int socket, unsigned requestedSize) {
00381 SOCKLEN_T sizeSize = sizeof requestedSize;
00382 setsockopt(socket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize);
00383
00384
00385 return getBufferSize(env, bufOptName, socket);
00386 }
00387 unsigned setSendBufferTo(UsageEnvironment& env,
00388 int socket, unsigned requestedSize) {
00389 return setBufferTo(env, SO_SNDBUF, socket, requestedSize);
00390 }
00391 unsigned setReceiveBufferTo(UsageEnvironment& env,
00392 int socket, unsigned requestedSize) {
00393 return setBufferTo(env, SO_RCVBUF, socket, requestedSize);
00394 }
00395
00396 static unsigned increaseBufferTo(UsageEnvironment& env, int bufOptName,
00397 int socket, unsigned requestedSize) {
00398
00399
00400 unsigned curSize = getBufferSize(env, bufOptName, socket);
00401
00402
00403
00404 while (requestedSize > curSize) {
00405 SOCKLEN_T sizeSize = sizeof requestedSize;
00406 if (setsockopt(socket, SOL_SOCKET, bufOptName,
00407 (char*)&requestedSize, sizeSize) >= 0) {
00408
00409 return requestedSize;
00410 }
00411 requestedSize = (requestedSize+curSize)/2;
00412 }
00413
00414 return getBufferSize(env, bufOptName, socket);
00415 }
00416 unsigned increaseSendBufferTo(UsageEnvironment& env,
00417 int socket, unsigned requestedSize) {
00418 return increaseBufferTo(env, SO_SNDBUF, socket, requestedSize);
00419 }
00420 unsigned increaseReceiveBufferTo(UsageEnvironment& env,
00421 int socket, unsigned requestedSize) {
00422 return increaseBufferTo(env, SO_RCVBUF, socket, requestedSize);
00423 }
00424
00425 Boolean socketJoinGroup(UsageEnvironment& env, int socket,
00426 netAddressBits groupAddress){
00427 if (!IsMulticastAddress(groupAddress)) return True;
00428
00429 struct ip_mreq imr;
00430 imr.imr_multiaddr.s_addr = groupAddress;
00431 imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00432 if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00433 (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00434 #if defined(__WIN32__) || defined(_WIN32)
00435 if (env.getErrno() != 0) {
00436
00437
00438 #endif
00439 socketErr(env, "setsockopt(IP_ADD_MEMBERSHIP) error: ");
00440 return False;
00441 #if defined(__WIN32__) || defined(_WIN32)
00442 }
00443 #endif
00444 }
00445
00446 return True;
00447 }
00448
00449 Boolean socketLeaveGroup(UsageEnvironment&, int socket,
00450 netAddressBits groupAddress) {
00451 if (!IsMulticastAddress(groupAddress)) return True;
00452
00453 struct ip_mreq imr;
00454 imr.imr_multiaddr.s_addr = groupAddress;
00455 imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00456 if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00457 (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00458 return False;
00459 }
00460
00461 return True;
00462 }
00463
00464
00465
00466
00467 #if !defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(__CYGWIN32__)
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 struct ip_mreq_source {
00478 struct in_addr imr_multiaddr;
00479 struct in_addr imr_sourceaddr;
00480 struct in_addr imr_interface;
00481 };
00482 #endif
00483
00484 #ifndef IP_ADD_SOURCE_MEMBERSHIP
00485
00486 #ifdef LINUX
00487 #define IP_ADD_SOURCE_MEMBERSHIP 39
00488 #define IP_DROP_SOURCE_MEMBERSHIP 40
00489 #else
00490 #define IP_ADD_SOURCE_MEMBERSHIP 25
00491 #define IP_DROP_SOURCE_MEMBERSHIP 26
00492 #endif
00493
00494 #endif
00495
00496 Boolean socketJoinGroupSSM(UsageEnvironment& env, int socket,
00497 netAddressBits groupAddress,
00498 netAddressBits sourceFilterAddr) {
00499 if (!IsMulticastAddress(groupAddress)) return True;
00500
00501 struct ip_mreq_source imr;
00502 imr.imr_multiaddr.s_addr = groupAddress;
00503 imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00504 imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00505 if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
00506 (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00507 socketErr(env, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP) error: ");
00508 return False;
00509 }
00510
00511 return True;
00512 }
00513
00514 Boolean socketLeaveGroupSSM(UsageEnvironment& , int socket,
00515 netAddressBits groupAddress,
00516 netAddressBits sourceFilterAddr) {
00517 if (!IsMulticastAddress(groupAddress)) return True;
00518
00519 struct ip_mreq_source imr;
00520 imr.imr_multiaddr.s_addr = groupAddress;
00521 imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00522 imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00523 if (setsockopt(socket, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP,
00524 (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00525 return False;
00526 }
00527
00528 return True;
00529 }
00530
00531 static Boolean getSourcePort0(int socket, portNumBits& resultPortNum) {
00532 sockaddr_in test; test.sin_port = 0;
00533 SOCKLEN_T len = sizeof test;
00534 if (getsockname(socket, (struct sockaddr*)&test, &len) < 0) return False;
00535
00536 resultPortNum = ntohs(test.sin_port);
00537 return True;
00538 }
00539
00540 Boolean getSourcePort(UsageEnvironment& env, int socket, Port& port) {
00541 portNumBits portNum = 0;
00542 if (!getSourcePort0(socket, portNum) || portNum == 0) {
00543
00544 MAKE_SOCKADDR_IN(name, INADDR_ANY, 0);
00545 bind(socket, (struct sockaddr*)&name, sizeof name);
00546
00547 if (!getSourcePort0(socket, portNum) || portNum == 0) {
00548 socketErr(env, "getsockname() error: ");
00549 return False;
00550 }
00551 }
00552
00553 port = Port(portNum);
00554 return True;
00555 }
00556
00557 static Boolean badAddress(netAddressBits addr) {
00558
00559 netAddressBits hAddr = ntohl(addr);
00560 return (hAddr == 0x7F000001
00561 || hAddr == 0
00562 || hAddr == (netAddressBits)(~0));
00563 }
00564
00565 Boolean loopbackWorks = 1;
00566
00567 netAddressBits ourIPAddress(UsageEnvironment& env) {
00568 static netAddressBits ourAddress = 0;
00569 int sock = -1;
00570 struct in_addr testAddr;
00571
00572 if (ourAddress == 0) {
00573
00574 struct sockaddr_in fromAddr;
00575 fromAddr.sin_addr.s_addr = 0;
00576
00577
00578
00579
00580
00581 do {
00582 loopbackWorks = 0;
00583
00584 testAddr.s_addr = our_inet_addr("228.67.43.91");
00585 Port testPort(15947);
00586
00587 sock = setupDatagramSocket(env, testPort);
00588 if (sock < 0) break;
00589
00590 if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;
00591
00592 unsigned char testString[] = "hostIdTest";
00593 unsigned testStringLength = sizeof testString;
00594
00595 if (!writeSocket(env, sock, testAddr, testPort, 0,
00596 testString, testStringLength)) break;
00597
00598 unsigned char readBuffer[20];
00599 struct timeval timeout;
00600 timeout.tv_sec = 5;
00601 timeout.tv_usec = 0;
00602 int bytesRead = readSocket(env, sock,
00603 readBuffer, sizeof readBuffer,
00604 fromAddr, &timeout);
00605 if (bytesRead == 0
00606 || bytesRead != (int)testStringLength
00607 || strncmp((char*)readBuffer, (char*)testString,
00608 testStringLength) != 0) {
00609 break;
00610 }
00611
00612 loopbackWorks = 1;
00613 } while (0);
00614
00615 if (!loopbackWorks) do {
00616
00617
00618 char hostname[100];
00619 hostname[0] = '\0';
00620 #ifndef CRIS
00621 gethostname(hostname, sizeof hostname);
00622 #endif
00623 if (hostname[0] == '\0') {
00624 env.setResultErrMsg("initial gethostname() failed");
00625 break;
00626 }
00627
00628 #if defined(VXWORKS)
00629 #include <hostLib.h>
00630 if (ERROR == (ourAddress = hostGetByName( hostname ))) break;
00631 #else
00632 struct hostent* hstent
00633 = (struct hostent*)gethostbyname(hostname);
00634 if (hstent == NULL || hstent->h_length != 4) {
00635 env.setResultErrMsg("initial gethostbyname() failed");
00636 break;
00637 }
00638
00639
00640 netAddressBits addr = 0;
00641 for (unsigned i = 0; ; ++i) {
00642 char* addrPtr = hstent->h_addr_list[i];
00643 if (addrPtr == NULL) break;
00644
00645 netAddressBits a = *(netAddressBits*)addrPtr;
00646 if (!badAddress(a)) {
00647 addr = a;
00648 break;
00649 }
00650 }
00651 if (addr != 0) {
00652 fromAddr.sin_addr.s_addr = addr;
00653 } else {
00654 env.setResultMsg("no address");
00655 break;
00656 }
00657 } while (0);
00658
00659
00660 netAddressBits from = fromAddr.sin_addr.s_addr;
00661 if (badAddress(from)) {
00662 char tmp[100];
00663 sprintf(tmp,
00664 "This computer has an invalid IP address: 0x%x",
00665 (netAddressBits)(ntohl(from)));
00666 env.setResultMsg(tmp);
00667 from = 0;
00668 }
00669
00670 ourAddress = from;
00671 #endif
00672
00673 if (sock >= 0) {
00674 socketLeaveGroup(env, sock, testAddr.s_addr);
00675 closeSocket(sock);
00676 }
00677
00678
00679
00680 struct timeval timeNow;
00681 gettimeofday(&timeNow, NULL);
00682 unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
00683 our_srandom(seed);
00684 }
00685 return ourAddress;
00686 }
00687
00688 netAddressBits chooseRandomIPv4SSMAddress(UsageEnvironment& env) {
00689
00690 (void) ourIPAddress(env);
00691
00692
00693
00694 netAddressBits const first = 0xE8000100, lastPlus1 = 0xE8FFFFFF;
00695 netAddressBits const range = lastPlus1 - first;
00696
00697 return htonl(first + ((netAddressBits)our_random())%range);
00698 }
00699
00700 char const* timestampString() {
00701 struct timeval tvNow;
00702 gettimeofday(&tvNow, NULL);
00703
00704 #if !defined(_WIN32_WCE)
00705 static char timeString[9];
00706 char const* ctimeResult = ctime((time_t*)&tvNow.tv_sec);
00707 char const* from = &ctimeResult[11];
00708 int i;
00709 for (i = 0; i < 8; ++i) {
00710 timeString[i] = from[i];
00711 }
00712 timeString[i] = '\0';
00713 #else
00714
00715
00716
00717 static char timeString[50];
00718 sprintf(timeString, "%lu.%06ld", tvNow.tv_sec, tvNow.tv_usec);
00719 #endif
00720
00721 return (char const*)&timeString;
00722 }
00723
00724 #if (defined(__WIN32__) || defined(_WIN32)) && !defined(IMN_PIM)
00725
00726 #if !defined(_WIN32_WCE)
00727 #include <sys/timeb.h>
00728 #endif
00729
00730 int gettimeofday(struct timeval* tp, int* ) {
00731 #if defined(_WIN32_WCE)
00732
00733 static const unsigned __int64 epoch = 116444736000000000L;
00734
00735 FILETIME file_time;
00736 SYSTEMTIME system_time;
00737 ULARGE_INTEGER ularge;
00738
00739 GetSystemTime(&system_time);
00740 SystemTimeToFileTime(&system_time, &file_time);
00741 ularge.LowPart = file_time.dwLowDateTime;
00742 ularge.HighPart = file_time.dwHighDateTime;
00743
00744 tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
00745 tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
00746 #else
00747 #ifdef USE_OLD_GETTIMEOFDAY_FOR_WINDOWS_CODE
00748 struct timeb tb;
00749 ftime(&tb);
00750 tp->tv_sec = tb.time;
00751 tp->tv_usec = 1000*tb.millitm;
00752 #else
00753 LARGE_INTEGER tickNow;
00754 static LARGE_INTEGER tickFrequency;
00755 static BOOL tickFrequencySet = FALSE;
00756 if (tickFrequencySet == FALSE) {
00757 QueryPerformanceFrequency(&tickFrequency);
00758 tickFrequencySet = TRUE;
00759 }
00760 QueryPerformanceCounter(&tickNow);
00761 tp->tv_sec = (long) (tickNow.QuadPart / tickFrequency.QuadPart);
00762 tp->tv_usec = (long) (((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);
00763 #endif
00764 #endif
00765 return 0;
00766 }
00767 #endif