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