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