1 /*****************************************************************************
2 Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above
10 copyright notice, this list of conditions and the
11 following disclaimer.
12
13 * Redistributions in binary form must reproduce the
14 above copyright notice, this list of conditions
15 and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17
18 * Neither the name of the University of Illinois
19 nor the names of its contributors may be used to
20 endorse or promote products derived from this
21 software without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *****************************************************************************/
35
36 /*****************************************************************************
37 written by
38 Yunhong Gu, last updated 07/25/2010
39 *****************************************************************************/
40
41
42 #ifndef WIN32
43 #include <cstring>
44 #include <cerrno>
45 #include <unistd.h>
46 #ifdef OSX
47 #include <mach/mach_time.h>
48 #endif
49 #else
50 #include <winsock2.h>
51 #include <ws2tcpip.h>
52 #ifdef LEGACY_WIN32
53 #include <wspiapi.h>
54 #endif
55 #endif
56
57 #include <cmath>
58 #include <md5.h>
59 #include "common.h"
60
61 bool CTimer::m_bUseMicroSecond = false;
62 uint64_t CTimer::s_ullCPUFrequency = CTimer::readCPUFrequency();
63 #ifndef WIN32
64 pthread_mutex_t CTimer::m_EventLock = PTHREAD_MUTEX_INITIALIZER;
65 pthread_cond_t CTimer::m_EventCond = PTHREAD_COND_INITIALIZER;
66 #else
67 pthread_mutex_t CTimer::m_EventLock = CreateMutex(NULL, false, NULL);
68 pthread_cond_t CTimer::m_EventCond = CreateEvent(NULL, false, false, NULL);
69 #endif
70
CTimer()71 CTimer::CTimer():
72 m_ullSchedTime(),
73 m_TickCond(),
74 m_TickLock()
75 {
76 #ifndef WIN32
77 pthread_mutex_init(&m_TickLock, NULL);
78 pthread_cond_init(&m_TickCond, NULL);
79 #else
80 m_TickLock = CreateMutex(NULL, false, NULL);
81 m_TickCond = CreateEvent(NULL, false, false, NULL);
82 #endif
83 }
84
~CTimer()85 CTimer::~CTimer()
86 {
87 #ifndef WIN32
88 pthread_mutex_destroy(&m_TickLock);
89 pthread_cond_destroy(&m_TickCond);
90 #else
91 CloseHandle(m_TickLock);
92 CloseHandle(m_TickCond);
93 #endif
94 }
95
rdtsc(uint64_t & x)96 void CTimer::rdtsc(uint64_t &x)
97 {
98 if (m_bUseMicroSecond)
99 {
100 x = getTime();
101 return;
102 }
103
104 #ifdef IA32
105 uint32_t lval, hval;
106 //asm volatile ("push %eax; push %ebx; push %ecx; push %edx");
107 //asm volatile ("xor %eax, %eax; cpuid");
108 asm volatile ("rdtsc" : "=a" (lval), "=d" (hval));
109 //asm volatile ("pop %edx; pop %ecx; pop %ebx; pop %eax");
110 x = hval;
111 x = (x << 32) | lval;
112 #elif defined(IA64)
113 asm ("mov %0=ar.itc" : "=r"(x) :: "memory");
114 #elif defined(AMD64)
115 uint32_t lval, hval;
116 asm ("rdtsc" : "=a" (lval), "=d" (hval));
117 x = hval;
118 x = (x << 32) | lval;
119 #elif defined(WIN32)
120 //HANDLE hCurThread = ::GetCurrentThread();
121 //DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
122 BOOL ret = QueryPerformanceCounter((LARGE_INTEGER *)&x);
123 //SetThreadAffinityMask(hCurThread, dwOldMask);
124 if (!ret)
125 x = getTime() * s_ullCPUFrequency;
126 #elif defined(OSX)
127 x = mach_absolute_time();
128 #else
129 // use system call to read time clock for other archs
130 x = getTime();
131 #endif
132 }
133
readCPUFrequency()134 uint64_t CTimer::readCPUFrequency()
135 {
136 uint64_t frequency = 1; // 1 tick per microsecond.
137
138 #if defined(IA32) || defined(IA64) || defined(AMD64)
139 uint64_t t1, t2;
140
141 rdtsc(t1);
142 timespec ts;
143 ts.tv_sec = 0;
144 ts.tv_nsec = 100000000;
145 nanosleep(&ts, NULL);
146 rdtsc(t2);
147
148 // CPU clocks per microsecond
149 frequency = (t2 - t1) / 100000;
150 #elif defined(WIN32)
151 int64_t ccf;
152 if (QueryPerformanceFrequency((LARGE_INTEGER *)&ccf))
153 frequency = ccf / 1000000;
154 #elif defined(OSX)
155 mach_timebase_info_data_t info;
156 mach_timebase_info(&info);
157 frequency = info.denom * 1000ULL / info.numer;
158 #endif
159
160 // Fall back to microsecond if the resolution is not high enough.
161 if (frequency < 10)
162 {
163 frequency = 1;
164 m_bUseMicroSecond = true;
165 }
166 return frequency;
167 }
168
getCPUFrequency()169 uint64_t CTimer::getCPUFrequency()
170 {
171 return s_ullCPUFrequency;
172 }
173
sleep(uint64_t interval)174 void CTimer::sleep(uint64_t interval)
175 {
176 uint64_t t;
177 rdtsc(t);
178
179 // sleep next "interval" time
180 sleepto(t + interval);
181 }
182
sleepto(uint64_t nexttime)183 void CTimer::sleepto(uint64_t nexttime)
184 {
185 // Use class member such that the method can be interrupted by others
186 m_ullSchedTime = nexttime;
187
188 uint64_t t;
189 rdtsc(t);
190
191 while (t < m_ullSchedTime)
192 {
193 #ifndef NO_BUSY_WAITING
194 #ifdef IA32
195 __asm__ volatile ("pause; rep; nop; nop; nop; nop; nop;");
196 #elif IA64
197 __asm__ volatile ("nop 0; nop 0; nop 0; nop 0; nop 0;");
198 #elif AMD64
199 __asm__ volatile ("nop; nop; nop; nop; nop;");
200 #endif
201 #else
202 #ifndef WIN32
203 timeval now;
204 timespec timeout;
205 gettimeofday(&now, 0);
206 if (now.tv_usec < 990000)
207 {
208 timeout.tv_sec = now.tv_sec;
209 timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
210 }
211 else
212 {
213 timeout.tv_sec = now.tv_sec + 1;
214 timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
215 }
216 pthread_mutex_lock(&m_TickLock);
217 pthread_cond_timedwait(&m_TickCond, &m_TickLock, &timeout);
218 pthread_mutex_unlock(&m_TickLock);
219 #else
220 WaitForSingleObject(m_TickCond, 1);
221 #endif
222 #endif
223
224 rdtsc(t);
225 }
226 }
227
interrupt()228 void CTimer::interrupt()
229 {
230 // schedule the sleepto time to the current CCs, so that it will stop
231 rdtsc(m_ullSchedTime);
232 tick();
233 }
234
tick()235 void CTimer::tick()
236 {
237 #ifndef WIN32
238 pthread_cond_signal(&m_TickCond);
239 #else
240 SetEvent(m_TickCond);
241 #endif
242 }
243
getTime()244 uint64_t CTimer::getTime()
245 {
246 //For Cygwin and other systems without microsecond level resolution, uncomment the following three lines
247 //uint64_t x;
248 //rdtsc(x);
249 //return x / s_ullCPUFrequency;
250 //Specific fix may be necessary if rdtsc is not available either.
251
252 #ifndef WIN32
253 timeval t;
254 gettimeofday(&t, 0);
255 return t.tv_sec * 1000000ULL + t.tv_usec;
256 #else
257 LARGE_INTEGER ccf;
258 HANDLE hCurThread = ::GetCurrentThread();
259 DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1);
260 if (QueryPerformanceFrequency(&ccf))
261 {
262 LARGE_INTEGER cc;
263 if (QueryPerformanceCounter(&cc))
264 {
265 SetThreadAffinityMask(hCurThread, dwOldMask);
266 return (cc.QuadPart * 1000000ULL / ccf.QuadPart);
267 }
268 }
269
270 SetThreadAffinityMask(hCurThread, dwOldMask);
271 return GetTickCount() * 1000ULL;
272 #endif
273 }
274
triggerEvent()275 void CTimer::triggerEvent()
276 {
277 #ifndef WIN32
278 pthread_cond_signal(&m_EventCond);
279 #else
280 SetEvent(m_EventCond);
281 #endif
282 }
283
waitForEvent()284 void CTimer::waitForEvent()
285 {
286 #ifndef WIN32
287 timeval now;
288 timespec timeout;
289 gettimeofday(&now, 0);
290 if (now.tv_usec < 990000)
291 {
292 timeout.tv_sec = now.tv_sec;
293 timeout.tv_nsec = (now.tv_usec + 10000) * 1000;
294 }
295 else
296 {
297 timeout.tv_sec = now.tv_sec + 1;
298 timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000;
299 }
300 pthread_mutex_lock(&m_EventLock);
301 pthread_cond_timedwait(&m_EventCond, &m_EventLock, &timeout);
302 pthread_mutex_unlock(&m_EventLock);
303 #else
304 WaitForSingleObject(m_EventCond, 1);
305 #endif
306 }
307
sleep()308 void CTimer::sleep()
309 {
310 #ifndef WIN32
311 usleep(10);
312 #else
313 Sleep(1);
314 #endif
315 }
316
317
318 //
319 // Automatically lock in constructor
CGuard(pthread_mutex_t & lock)320 CGuard::CGuard(pthread_mutex_t& lock):
321 m_Mutex(lock),
322 m_iLocked()
323 {
324 #ifndef WIN32
325 m_iLocked = pthread_mutex_lock(&m_Mutex);
326 #else
327 m_iLocked = WaitForSingleObject(m_Mutex, INFINITE);
328 #endif
329 }
330
331 // Automatically unlock in destructor
~CGuard()332 CGuard::~CGuard()
333 {
334 #ifndef WIN32
335 if (0 == m_iLocked)
336 pthread_mutex_unlock(&m_Mutex);
337 #else
338 if (WAIT_FAILED != m_iLocked)
339 ReleaseMutex(m_Mutex);
340 #endif
341 }
342
enterCS(pthread_mutex_t & lock)343 void CGuard::enterCS(pthread_mutex_t& lock)
344 {
345 #ifndef WIN32
346 pthread_mutex_lock(&lock);
347 #else
348 WaitForSingleObject(lock, INFINITE);
349 #endif
350 }
351
leaveCS(pthread_mutex_t & lock)352 void CGuard::leaveCS(pthread_mutex_t& lock)
353 {
354 #ifndef WIN32
355 pthread_mutex_unlock(&lock);
356 #else
357 ReleaseMutex(lock);
358 #endif
359 }
360
createMutex(pthread_mutex_t & lock)361 void CGuard::createMutex(pthread_mutex_t& lock)
362 {
363 #ifndef WIN32
364 pthread_mutex_init(&lock, NULL);
365 #else
366 lock = CreateMutex(NULL, false, NULL);
367 #endif
368 }
369
releaseMutex(pthread_mutex_t & lock)370 void CGuard::releaseMutex(pthread_mutex_t& lock)
371 {
372 #ifndef WIN32
373 pthread_mutex_destroy(&lock);
374 #else
375 CloseHandle(lock);
376 #endif
377 }
378
createCond(pthread_cond_t & cond)379 void CGuard::createCond(pthread_cond_t& cond)
380 {
381 #ifndef WIN32
382 pthread_cond_init(&cond, NULL);
383 #else
384 cond = CreateEvent(NULL, false, false, NULL);
385 #endif
386 }
387
releaseCond(pthread_cond_t & cond)388 void CGuard::releaseCond(pthread_cond_t& cond)
389 {
390 #ifndef WIN32
391 pthread_cond_destroy(&cond);
392 #else
393 CloseHandle(cond);
394 #endif
395
396 }
397
398 //
CUDTException(int major,int minor,int err)399 CUDTException::CUDTException(int major, int minor, int err):
400 m_iMajor(major),
401 m_iMinor(minor)
402 {
403 if (-1 == err)
404 #ifndef WIN32
405 m_iErrno = errno;
406 #else
407 m_iErrno = GetLastError();
408 #endif
409 else
410 m_iErrno = err;
411 }
412
CUDTException(const CUDTException & e)413 CUDTException::CUDTException(const CUDTException& e):
414 m_iMajor(e.m_iMajor),
415 m_iMinor(e.m_iMinor),
416 m_iErrno(e.m_iErrno),
417 m_strMsg()
418 {
419 }
420
~CUDTException()421 CUDTException::~CUDTException()
422 {
423 }
424
getErrorMessage()425 const char* CUDTException::getErrorMessage()
426 {
427 // translate "Major:Minor" code into text message.
428
429 switch (m_iMajor)
430 {
431 case 0:
432 m_strMsg = "Success";
433 break;
434
435 case 1:
436 m_strMsg = "Connection setup failure";
437
438 switch (m_iMinor)
439 {
440 case 1:
441 m_strMsg += ": connection time out";
442 break;
443
444 case 2:
445 m_strMsg += ": connection rejected";
446 break;
447
448 case 3:
449 m_strMsg += ": unable to create/configure UDP socket";
450 break;
451
452 case 4:
453 m_strMsg += ": abort for security reasons";
454 break;
455
456 default:
457 break;
458 }
459
460 break;
461
462 case 2:
463 switch (m_iMinor)
464 {
465 case 1:
466 m_strMsg = "Connection was broken";
467 break;
468
469 case 2:
470 m_strMsg = "Connection does not exist";
471 break;
472
473 default:
474 break;
475 }
476
477 break;
478
479 case 3:
480 m_strMsg = "System resource failure";
481
482 switch (m_iMinor)
483 {
484 case 1:
485 m_strMsg += ": unable to create new threads";
486 break;
487
488 case 2:
489 m_strMsg += ": unable to allocate buffers";
490 break;
491
492 default:
493 break;
494 }
495
496 break;
497
498 case 4:
499 m_strMsg = "File system failure";
500
501 switch (m_iMinor)
502 {
503 case 1:
504 m_strMsg += ": cannot seek read position";
505 break;
506
507 case 2:
508 m_strMsg += ": failure in read";
509 break;
510
511 case 3:
512 m_strMsg += ": cannot seek write position";
513 break;
514
515 case 4:
516 m_strMsg += ": failure in write";
517 break;
518
519 default:
520 break;
521 }
522
523 break;
524
525 case 5:
526 m_strMsg = "Operation not supported";
527
528 switch (m_iMinor)
529 {
530 case 1:
531 m_strMsg += ": Cannot do this operation on a BOUND socket";
532 break;
533
534 case 2:
535 m_strMsg += ": Cannot do this operation on a CONNECTED socket";
536 break;
537
538 case 3:
539 m_strMsg += ": Bad parameters";
540 break;
541
542 case 4:
543 m_strMsg += ": Invalid socket ID";
544 break;
545
546 case 5:
547 m_strMsg += ": Cannot do this operation on an UNBOUND socket";
548 break;
549
550 case 6:
551 m_strMsg += ": Socket is not in listening state";
552 break;
553
554 case 7:
555 m_strMsg += ": Listen/accept is not supported in rendezous connection setup";
556 break;
557
558 case 8:
559 m_strMsg += ": Cannot call connect on UNBOUND socket in rendezvous connection setup";
560 break;
561
562 case 9:
563 m_strMsg += ": This operation is not supported in SOCK_STREAM mode";
564 break;
565
566 case 10:
567 m_strMsg += ": This operation is not supported in SOCK_DGRAM mode";
568 break;
569
570 case 11:
571 m_strMsg += ": Another socket is already listening on the same port";
572 break;
573
574 case 12:
575 m_strMsg += ": Message is too large to send (it must be less than the UDT send buffer size)";
576 break;
577
578 case 13:
579 m_strMsg += ": Invalid epoll ID";
580 break;
581
582 default:
583 break;
584 }
585
586 break;
587
588 case 6:
589 m_strMsg = "Non-blocking call failure";
590
591 switch (m_iMinor)
592 {
593 case 1:
594 m_strMsg += ": no buffer available for sending";
595 break;
596
597 case 2:
598 m_strMsg += ": no data available for reading";
599 break;
600
601 default:
602 break;
603 }
604
605 break;
606
607 case 7:
608 m_strMsg = "The peer side has signalled an error";
609
610 break;
611
612 default:
613 m_strMsg = "Unknown error";
614 }
615
616 // Adding "errno" information
617 if ((0 != m_iMajor) && (0 < m_iErrno))
618 {
619 m_strMsg += ": ";
620 #ifndef WIN32
621 char errmsg[1024];
622 if (strerror_r(m_iErrno, errmsg, 1024) == 0)
623 m_strMsg += errmsg;
624 #else
625 LPVOID lpMsgBuf;
626 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_iErrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
627 m_strMsg += (char*)lpMsgBuf;
628 LocalFree(lpMsgBuf);
629 #endif
630 }
631
632 // period
633 #ifndef WIN32
634 m_strMsg += ".";
635 #endif
636
637 return m_strMsg.c_str();
638 }
639
getErrorCode() const640 int CUDTException::getErrorCode() const
641 {
642 return m_iMajor * 1000 + m_iMinor;
643 }
644
clear()645 void CUDTException::clear()
646 {
647 m_iMajor = 0;
648 m_iMinor = 0;
649 m_iErrno = 0;
650 }
651
652 const int CUDTException::SUCCESS = 0;
653 const int CUDTException::ECONNSETUP = 1000;
654 const int CUDTException::ENOSERVER = 1001;
655 const int CUDTException::ECONNREJ = 1002;
656 const int CUDTException::ESOCKFAIL = 1003;
657 const int CUDTException::ESECFAIL = 1004;
658 const int CUDTException::ECONNFAIL = 2000;
659 const int CUDTException::ECONNLOST = 2001;
660 const int CUDTException::ENOCONN = 2002;
661 const int CUDTException::ERESOURCE = 3000;
662 const int CUDTException::ETHREAD = 3001;
663 const int CUDTException::ENOBUF = 3002;
664 const int CUDTException::EFILE = 4000;
665 const int CUDTException::EINVRDOFF = 4001;
666 const int CUDTException::ERDPERM = 4002;
667 const int CUDTException::EINVWROFF = 4003;
668 const int CUDTException::EWRPERM = 4004;
669 const int CUDTException::EINVOP = 5000;
670 const int CUDTException::EBOUNDSOCK = 5001;
671 const int CUDTException::ECONNSOCK = 5002;
672 const int CUDTException::EINVPARAM = 5003;
673 const int CUDTException::EINVSOCK = 5004;
674 const int CUDTException::EUNBOUNDSOCK = 5005;
675 const int CUDTException::ENOLISTEN = 5006;
676 const int CUDTException::ERDVNOSERV = 5007;
677 const int CUDTException::ERDVUNBOUND = 5008;
678 const int CUDTException::ESTREAMILL = 5009;
679 const int CUDTException::EDGRAMILL = 5010;
680 const int CUDTException::EDUPLISTEN = 5011;
681 const int CUDTException::ELARGEMSG = 5012;
682 const int CUDTException::EINVPOLLID = 5013;
683 const int CUDTException::EASYNCFAIL = 6000;
684 const int CUDTException::EASYNCSND = 6001;
685 const int CUDTException::EASYNCRCV = 6002;
686 const int CUDTException::ETIMEOUT = 6003;
687 const int CUDTException::EPEERERR = 7000;
688 const int CUDTException::EUNKNOWN = -1;
689
690
691 //
ipcmp(const sockaddr * addr1,const sockaddr * addr2,int ver)692 bool CIPAddress::ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver)
693 {
694 if (AF_INET == ver)
695 {
696 sockaddr_in* a1 = (sockaddr_in*)addr1;
697 sockaddr_in* a2 = (sockaddr_in*)addr2;
698
699 if ((a1->sin_port == a2->sin_port) && (a1->sin_addr.s_addr == a2->sin_addr.s_addr))
700 return true;
701 }
702 else
703 {
704 sockaddr_in6* a1 = (sockaddr_in6*)addr1;
705 sockaddr_in6* a2 = (sockaddr_in6*)addr2;
706
707 if (a1->sin6_port == a2->sin6_port)
708 {
709 for (int i = 0; i < 16; ++ i)
710 if (*((char*)&(a1->sin6_addr) + i) != *((char*)&(a2->sin6_addr) + i))
711 return false;
712
713 return true;
714 }
715 }
716
717 return false;
718 }
719
ntop(const sockaddr * addr,uint32_t ip[4],int ver)720 void CIPAddress::ntop(const sockaddr* addr, uint32_t ip[4], int ver)
721 {
722 if (AF_INET == ver)
723 {
724 sockaddr_in* a = (sockaddr_in*)addr;
725 ip[0] = a->sin_addr.s_addr;
726 }
727 else
728 {
729 sockaddr_in6* a = (sockaddr_in6*)addr;
730 ip[3] = (a->sin6_addr.s6_addr[15] << 24) + (a->sin6_addr.s6_addr[14] << 16) + (a->sin6_addr.s6_addr[13] << 8) + a->sin6_addr.s6_addr[12];
731 ip[2] = (a->sin6_addr.s6_addr[11] << 24) + (a->sin6_addr.s6_addr[10] << 16) + (a->sin6_addr.s6_addr[9] << 8) + a->sin6_addr.s6_addr[8];
732 ip[1] = (a->sin6_addr.s6_addr[7] << 24) + (a->sin6_addr.s6_addr[6] << 16) + (a->sin6_addr.s6_addr[5] << 8) + a->sin6_addr.s6_addr[4];
733 ip[0] = (a->sin6_addr.s6_addr[3] << 24) + (a->sin6_addr.s6_addr[2] << 16) + (a->sin6_addr.s6_addr[1] << 8) + a->sin6_addr.s6_addr[0];
734 }
735 }
736
pton(sockaddr * addr,const uint32_t ip[4],int ver)737 void CIPAddress::pton(sockaddr* addr, const uint32_t ip[4], int ver)
738 {
739 if (AF_INET == ver)
740 {
741 sockaddr_in* a = (sockaddr_in*)addr;
742 a->sin_addr.s_addr = ip[0];
743 }
744 else
745 {
746 sockaddr_in6* a = (sockaddr_in6*)addr;
747 for (int i = 0; i < 4; ++ i)
748 {
749 a->sin6_addr.s6_addr[i * 4] = ip[i] & 0xFF;
750 a->sin6_addr.s6_addr[i * 4 + 1] = (unsigned char)((ip[i] & 0xFF00) >> 8);
751 a->sin6_addr.s6_addr[i * 4 + 2] = (unsigned char)((ip[i] & 0xFF0000) >> 16);
752 a->sin6_addr.s6_addr[i * 4 + 3] = (unsigned char)((ip[i] & 0xFF000000) >> 24);
753 }
754 }
755 }
756
757 //
compute(const char * input,size_t ilen,unsigned char result[16])758 void CMD5::compute(const char* input, size_t ilen, unsigned char result[16])
759 {
760 MD5_CTX state;
761
762 MD5Init(&state);
763 MD5Update(&state, (const void *)input, ilen);
764 MD5Final(result, &state);
765 }
766
compute(const char * input,unsigned char result[16])767 void CMD5::compute(const char* input, unsigned char result[16])
768 {
769 compute(input, strlen(input), result);
770 }
771