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