reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
StunMessage.cxx
Go to the documentation of this file.
1
2#if defined(HAVE_CONFIG_H)
3#include "config.h"
4#endif
5
6#include "StunMessage.hxx"
7
8#include <rutil/compat.hxx>
9#include <rutil/Crc32.hxx>
10#include <rutil/Timer.hxx>
11#include <rutil/Random.hxx>
12#include <rutil/DataStream.hxx>
15#include <rutil/Logger.hxx>
16#include "ReTurnSubsystem.hxx"
17
18#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
19
20#ifdef USE_SSL
21#include <openssl/hmac.h>
22#else
23#include <rutil/Sha1.hxx>
24#endif
25
26using namespace std;
27using namespace resip;
28
29// What should we set these to? Used for short term password generation.
30static const Data USERNAME_KEY("stunServerUsernameKey");
31static const Data PASSWORD_KEY("stunServerPasswordKey");
32
33#define MAX_USERNAME_BYTES 512
34#define MAX_PASSWORD_BYTES 512
35#define MAX_REALM_BYTES 763
36#define MAX_NONCE_BYTES 763
37#define MAX_SOFTWARE_BYTES 763
38#define MAX_ERRORCODE_REASON_BYTES 763
39
40#define STUN_CRC_FINAL_XOR 0x5354554e
41
42namespace reTurn {
43
44bool operator<(const UInt128& lhs, const UInt128& rhs)
45{
46 if (lhs.longpart[0] != rhs.longpart[0])
47 {
48 return lhs.longpart[0] < rhs.longpart[0];
49 }
50 else if (lhs.longpart[1] != rhs.longpart[1])
51 {
52 return lhs.longpart[1] < rhs.longpart[1];
53 }
54 else if (lhs.longpart[2] != rhs.longpart[2])
55 {
56 return lhs.longpart[2] < rhs.longpart[2];
57 }
58
59 return lhs.longpart[3] < rhs.longpart[3];
60}
61
62bool operator==(const UInt128& lhs, const UInt128& rhs)
63{
64 return lhs.longpart[0] == rhs.longpart[0] &&
65 lhs.longpart[1] == rhs.longpart[1] &&
66 lhs.longpart[2] == rhs.longpart[2] &&
67 lhs.longpart[3] == rhs.longpart[3];
68}
69
71 const StunTuple& remoteTuple,
72 char* buf, unsigned int bufLen) :
73 mLocalTuple(localTuple),
74 mRemoteTuple(remoteTuple),
75 mBuffer(buf, bufLen) // !slg! copies buffer from Socket buffer assuming for now that StunMessages will persist past one request/response transaction
76 // could make this more efficient by having the transports allocate buffer dynamically and pass ownership over
77{
78 init();
79 mIsValid = stunParseMessage(buf, bufLen);
80
81 if (mIsValid)
82 {
83 DebugLog(<< "Successfully parsed StunMessage: " << mHeader);
84 }
85}
86
88 mIsValid(true)
89{
90 init();
91}
92
94{
95 *this = from;
96}
97
100{
101 if (this != &rhs)
102 {
103 resip_assert(false);
104 }
105
106 return *this;
107}
108
110{
112 if (mUsername) delete mUsername;
113 if (mPassword) delete mPassword;
114 if (mRealm) delete mRealm;
115 if (mNonce) delete mNonce;
116 if (mSoftware) delete mSoftware;
117 if (mTurnData) delete mTurnData;
118}
119
120void
121StunMessage::init()
122{
123 mHasMappedAddress = false;
124 mHasResponseAddress = false;
125 mHasChangeRequest = false;
126 mHasSourceAddress = false;
127 mHasChangedAddress = false;
128 mHasUsername = false;
129 mHasNonce = false;
130 mHasRealm = false;
131 mHasPassword = false;
132 mHasMessageIntegrity = false;
134 mHasErrorCode = false;
135 mHasUnknownAttributes = false;
136 mHasReflectedFrom = false;
137 mHasXorMappedAddress = false;
138 mHasFingerprint = false;
139 mHasSoftware = false;
140 mHasAlternateServer = false;
141 mHasSecondaryAddress = false;
142 mHasTurnChannelNumber = false;
143 mHasTurnLifetime = false;
144 mHasTurnBandwidth = false;
145 mHasTurnData = false;
147 mHasTurnEvenPort = false;
149 mHasTurnDontFragment = false;
151 mHasTurnConnectStat = false;
154 mHasIcePriority = false;
155 mIcePriority = 0;
156 mHasIceUseCandidate = false;
157 mHasIceControlled = false;
159 mHasIceControlling = false;
161 mErrorCode.reason = 0;
162 mUsername = 0;
163 mPassword = 0;
164 mRealm = 0;
165 mNonce = 0;
166 mSoftware = 0;
167 mTurnData = 0;
171}
172
173void
175{
176 mClass = stunclass;
177 mMethod = method;
178
179 // Assign a tid
181 Data random = Random::getCryptoRandom(12);
182 memcpy(&mHeader.id.tid, random.data(), sizeof(mHeader.id.tid));
183}
184
185void
186StunMessage::setErrorCode(unsigned short errorCode, const char* reason)
187{
188 resip_assert(errorCode >= 100 && errorCode <= 699);
189 mHasErrorCode = true;
190 mErrorCode.errorClass = errorCode / 100;
191 mErrorCode.number = errorCode % 100;
192 if (mErrorCode.reason)
193 {
194 *mErrorCode.reason = reason;
195 }
196 else
197 {
198 mErrorCode.reason = new Data(reason);
199 }
200}
201
202void
203StunMessage::setUsername(const char* username)
204{
205 mHasUsername = true;
206 if (mUsername)
207 {
208 *mUsername = username;
209 }
210 else
211 {
212 mUsername = new Data(username);
213 }
214}
215
216void
217StunMessage::setPassword(const char* password)
218{
219 mHasPassword = true;
220 if (mPassword)
221 {
222 *mPassword = password;
223 }
224 else
225 {
226 mPassword = new Data(password);
227 }
228}
229
230void
231StunMessage::setRealm(const char* realm)
232{
233 mHasRealm = true;
234 if (mRealm)
235 {
236 *mRealm = realm;
237 }
238 else
239 {
240 mRealm = new Data(realm);
241 }
242}
243
244void
245StunMessage::setNonce(const char* nonce)
246{
247 mHasNonce = true;
248 if (mNonce)
249 {
250 *mNonce = nonce;
251 }
252 else
253 {
254 mNonce = new Data(nonce);
255 }
256}
257
258void
259StunMessage::setSoftware(const char* software)
260{
261 mHasSoftware = true;
262 if (mSoftware)
263 {
264 *mSoftware = software;
265 }
266 else
267 {
268 mSoftware = new Data(software);
269 }
270}
271
272void
273StunMessage::setTurnData(const char* data, unsigned int len)
274{
275 mHasTurnData = true;
276 if (mTurnData)
277 {
278 mTurnData->clear();
279 mTurnData->append(data, len);
280 }
281 else
282 {
283 mTurnData = new Data(data, len);
284 }
285}
286
287void
289{
290 mHasIcePriority = true;
291 mIcePriority = priority;
292}
293
294void
299
300void
302{
303 mHasIceControlled = true;
304 const resip::Data& tieBreaker = resip::Random::getCryptoRandom(8);
305 memcpy(&mIceControlledTieBreaker, tieBreaker.begin(), sizeof(mIceControlledTieBreaker));
306}
307
308void
315
316void
318{
319 if (&in != &out) memcpy(&out, &in, sizeof(out));
320
321 out.port = out.port ^ (StunMessage::StunMagicCookie >> 16); // Xor with most significate 16 bits of magic cookie
322 if (out.family == IPv6Family)
323 {
324 for (int i = 0; i < 4; i++)
325 {
326 // Note: MagicCookieAndTid are stored in network byte order
328 }
329 }
330 else
331 {
333 }
334}
335
336void
338{
339 address.port = tuple.getPort();
340 if (tuple.getAddress().is_v6())
341 {
342 // Note: addr.ipv6 is stored in network byte order
344 memcpy(&address.addr.ipv6, tuple.getAddress().to_v6().to_bytes().data(), sizeof(address.addr.ipv6));
345 }
346 else
347 {
348 // Note: addr.ipv4 is stored in host byte order
350 address.addr.ipv4 = tuple.getAddress().to_v4().to_uint();
351 }
352}
353
354void
356{
357 tuple.setPort(address.port);
358 if (address.family == StunMessage::IPv6Family)
359 {
360 // Note: addr.ipv6 is stored in network byte order
361 asio::ip::address_v6::bytes_type bytes;
362 memcpy(bytes.data(), &address.addr.ipv6, bytes.size());
363 asio::ip::address_v6 addr(bytes);
364 tuple.setAddress(addr);
365 }
366 else
367 {
368 // Note: addr.ipv4 is stored in host byte order
369 asio::ip::address_v4 addr(address.addr.ipv4);
370 tuple.setAddress(addr);
371 }
372}
373
374bool
375StunMessage::stunParseAtrXorAddress(char* body, unsigned int hdrLen, StunAtrAddress& result)
376{
377 bool ret = stunParseAtrAddress(body, hdrLen, result);
378 if (ret)
379 {
380 applyXorToAddress(result, result);
381 }
382 return ret;
383}
384
385bool
386StunMessage::stunParseAtrAddress(char* body, unsigned int hdrLen, StunAtrAddress& result)
387{
388 if (hdrLen != 8 /* ipv4 size */ && hdrLen != 20 /* ipv6 size */)
389 {
390 WarningLog(<< "hdrLen wrong for Address");
391 return false;
392 }
393 body++; // Skip pad
394 result.family = *body++;
395
396 uint16_t nport;
397 memcpy(&nport, body, 2); body += 2;
398 result.port = ntohs(nport);
399
400 if (result.family == IPv4Family && hdrLen == 8)
401 {
402 uint32_t naddr;
403 memcpy(&naddr, body, sizeof(uint32_t)); body += sizeof(uint32_t);
404 result.addr.ipv4 = ntohl(naddr);
405 // Note: addr.ipv4 is stored in host byte order
406 return true;
407 }
408 else if (result.family == IPv6Family && hdrLen == 20)
409 {
410 memcpy(&result.addr.ipv6, body, sizeof(result.addr.ipv6)); body += sizeof(result.addr.ipv6);
411 // Note: addr.ipv6 is stored in host byte order
412 return true;
413 }
414 else
415 {
416 WarningLog(<< "bad address family/length: family=" << int(result.family) << " hdrLen=" << hdrLen);
417 }
418
419 return false;
420}
421
422bool
423StunMessage::stunParseAtrEvenPort(char* body, unsigned int hdrLen, TurnAtrEvenPort& result)
424{
425 if (hdrLen != 1)
426 {
427 WarningLog(<< "hdrLen wrong for EvenPort");
428 return false;
429 }
430 result.propType = *body & 0x80; // copy first 8 bits into propType - but only look at highest order
431
432 return true;
433}
434
435bool
436StunMessage::stunParseAtrUInt32(char* body, unsigned int hdrLen, uint32_t& result)
437{
438 if (hdrLen != 4)
439 {
440 WarningLog(<< "hdrLen wrong for UInt32 attribute");
441 return false;
442 }
443 else
444 {
445 memcpy(&result, body, 4);
446 result = ntohl(result);
447 return true;
448 }
449}
450
451bool
452StunMessage::stunParseAtrUInt64(char* body, unsigned int hdrLen, uint64_t& result)
453{
454 if (hdrLen != 8)
455 {
456 WarningLog(<< "hdrLen wrong for UInt64 attribute");
457 return false;
458 }
459 else
460 {
461 memcpy(&result, body, 8);
462 result = ntoh64(result);
463 return true;
464 }
465}
466
467bool
468StunMessage::stunParseAtrError(char* body, unsigned int hdrLen, StunAtrError& result)
469{
470 // Ensure min len
471 if (hdrLen < 4) return false;
472
473 body += 2; // skip pad
474 result.errorClass = *body++ & 0x7;
475 result.number = *body++;
476
477 int reasonLen = (hdrLen - 4) > MAX_ERRORCODE_REASON_BYTES ? MAX_ERRORCODE_REASON_BYTES : hdrLen - 4;
478 result.reason = new resip::Data(resip::Data::Share, body, reasonLen);
479 return true;
480}
481
482bool
483StunMessage::stunParseAtrUnknown(char* body, unsigned int hdrLen, StunAtrUnknown& result)
484{
485 if (hdrLen >= sizeof(result))
486 {
487 WarningLog(<< "hdrLen wrong for Unknown attribute or too many unknown attributes present");
488 return false;
489 }
490 else
491 {
492 if (hdrLen % 2 != 0) return false;
493 result.numAttributes = hdrLen / 2;
494 for (int i = 0; i < result.numAttributes; i++)
495 {
496 memcpy(&result.attrType[i], body, 2); body += 2;
497 result.attrType[i] = ntohs(result.attrType[i]);
498 }
499 return true;
500 }
501}
502
503bool
504StunMessage::stunParseAtrIntegrity(char* body, unsigned int hdrLen, StunAtrIntegrity& result)
505{
506 if (hdrLen != 20)
507 {
508 WarningLog(<< "hdrLen wrong for message integrity");
509 return false;
510 }
511 else
512 {
513 memcpy(&result.hash, body, hdrLen);
514 return true;
515 }
516}
517
518bool
519StunMessage::stunParseAtrIntegritySha256(char* body, unsigned int hdrLen, StunAtrIntegritySha256& result)
520{
521 // RFC 8489 permits truncation to a multiple of 4 bytes (>= 16), but for the
522 // short-term credential use case we only accept the full 32-byte HMAC-SHA256.
523 if (hdrLen != 32)
524 {
525 WarningLog(<< "hdrLen wrong for message integrity sha256 (only full 32-byte value supported)");
526 return false;
527 }
528 else
529 {
530 memcpy(&result.hash, body, hdrLen);
531 return true;
532 }
533}
534
535
536
537bool
538StunMessage::stunParseMessage(char* buf, unsigned int bufLen)
539{
540 StackLog(<< "Received stun message: " << bufLen << " bytes");
541
542 if (sizeof(StunMsgHdr) > bufLen)
543 {
544 WarningLog(<< "Bad message, bufLen=" << bufLen);
545 return false;
546 }
547
548 memcpy(&mHeader, buf, sizeof(StunMsgHdr));
551
552 if (mHeader.msgLength + sizeof(StunMsgHdr) != bufLen)
553 {
554 WarningLog(<< "Message header length (" << mHeader.msgLength << ") + header size (" << sizeof(StunMsgHdr) << ") doesn't match message size (" << bufLen << ")");
555 return false;
556 }
557
558 // Check if class and method are valid
559 mClass = mHeader.msgType & 0x0110;
560 mMethod = mHeader.msgType & 0x000F;
561
562 // Look for stun magic cookie
564 if (!mHasMagicCookie)
565 {
566 StackLog(<< "stun magic cookie not found.");
567 }
568
569 char* body = buf + sizeof(StunMsgHdr);
570 unsigned int size = mHeader.msgLength;
572
573 StackLog(<< "bytes after header = " << size);
574
575 while (size > 0)
576 {
577 if (size < sizeof(StunAtrHdr))
578 {
579 WarningLog(<< "Bad message, " << size << " bytes left is too short for an attribute header");
580 return false;
581 }
582
583 StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body);
584
585 unsigned int attrLen = ntohs(attr->length);
586 // attrLen may not be on 4 byte boundary, in which case we need to pad to 4 bytes when advancing to next attribute
587 unsigned int attrLenPad = attrLen % 4 == 0 ? 0 : 4 - (attrLen % 4);
588 int atrType = ntohs(attr->type);
589
590 StackLog(<< "Found attribute type=" << atrType << " length=" << attrLen);
591 if (attrLen + attrLenPad + 4 > size)
592 {
593 WarningLog(<< "claims attribute is larger than size of message " << "(attribute type=" << atrType << ")");
594 return false;
595 }
596
597 body += 4; // skip the length and type in attribute header
598 size -= 4;
599
600 switch (atrType)
601 {
602 case MappedAddress:
604 {
605 mHasMappedAddress = true;
606 if (stunParseAtrAddress(body, attrLen, mMappedAddress) == false)
607 {
608 WarningLog(<< "problem parsing MappedAddress");
609 return false;
610 }
611 StackLog(<< "MappedAddress = " << mMappedAddress);
612 }
613 else
614 {
615 WarningLog(<< "Duplicate MappedAddress in message - ignoring.");
616 }
617 break;
618
619 case ResponseAddress: // deprecated
621 {
622 mHasResponseAddress = true;
623 if (stunParseAtrAddress(body, attrLen, mResponseAddress) == false)
624 {
625 WarningLog(<< "problem parsing ResponseAddress");
626 return false;
627 }
628 StackLog(<< "ResponseAddress = " << mResponseAddress);
629 }
630 else
631 {
632 WarningLog(<< "Duplicate ResponseAddress in message - ignoring.");
633 }
634 break;
635
636 case ChangeRequest: // deprecated
638 {
639 mHasChangeRequest = true;
640 if (stunParseAtrUInt32(body, attrLen, mChangeRequest) == false)
641 {
642 WarningLog(<< "problem parsing ChangeRequest");
643 return false;
644 }
645 StackLog(<< "ChangeRequest = " << mChangeRequest);
646 }
647 else
648 {
649 WarningLog(<< "Duplicate ChangeRequest in message - ignoring.");
650 }
651 break;
652
653 case SourceAddress: // deprecated
655 {
656 mHasSourceAddress = true;
657 if (stunParseAtrAddress(body, attrLen, mSourceAddress) == false)
658 {
659 WarningLog(<< "problem parsing SourceAddress");
660 return false;
661 }
662 StackLog(<< "SourceAddress = " << mSourceAddress);
663 }
664 else
665 {
666 WarningLog(<< "Duplicate SourceAddress in message - ignoring.");
667 }
668 break;
669
670 case ChangedAddress: // deprecated
672 {
673 mHasChangedAddress = true;
674 if (stunParseAtrAddress(body, attrLen, mChangedAddress) == false)
675 {
676 WarningLog(<< "problem parsing ChangedAddress");
677 return false;
678 }
679 StackLog(<< "ChangedAddress = " << mChangedAddress);
680 }
681 else
682 {
683 WarningLog(<< "Duplicate ChangedAddress in message - ignoring.");
684 }
685 break;
686
687 case Username:
688 if (!mHasUsername)
689 {
690 if (attrLen > MAX_USERNAME_BYTES)
691 {
692 WarningLog(<< "Username length=" << attrLen << " is longer than max allowed=" << MAX_USERNAME_BYTES);
693 return false;
694 }
695 mHasUsername = true;
696 mUsername = new resip::Data(resip::Data::Share, body, attrLen);
697 StackLog(<< "Username = " << *mUsername);
698 }
699 else
700 {
701 WarningLog(<< "Duplicate Username in message - ignoring.");
702 }
703 break;
704
705 case Password:
706 if (!mHasPassword)
707 {
708 if (attrLen > MAX_PASSWORD_BYTES)
709 {
710 WarningLog(<< "Password length=" << attrLen << " is longer than max allowed=" << MAX_PASSWORD_BYTES);
711 return false;
712 }
713 mHasPassword = true;
714 mPassword = new resip::Data(resip::Data::Share, body, attrLen);
715 StackLog(<< "Password = " << *mPassword);
716 }
717 else
718 {
719 WarningLog(<< "Duplicate Password in message - ignoring.");
720 }
721 break;
722
723 case MessageIntegrity:
725 {
727 if (stunParseAtrIntegrity(body, attrLen, mMessageIntegrity) == false)
728 {
729 WarningLog(<< "problem parsing MessageIntegrity");
730 return false;
731 }
732 //StackLog(<< "MessageIntegrity = " << mMessageIntegrity.hash);
733 mMessageIntegrityMsgLength = (uint16_t)(body + attrLen - buf - sizeof(StunMsgHdr));
734 }
735 else
736 {
737 WarningLog(<< "Duplicate MessageIntegrity in message - ignoring.");
738 }
739 break;
740
743 {
745 if (stunParseAtrIntegritySha256(body, attrLen, mMessageIntegritySha256) == false)
746 {
747 WarningLog(<< "problem parsing MessageIntegritySha256");
748 return false;
749 }
750 mMessageIntegritySha256MsgLength = (uint16_t)(body + attrLen - buf - sizeof(StunMsgHdr));
751 }
752 else
753 {
754 WarningLog(<< "Duplicate MessageIntegritySha256 in message - ignoring.");
755 }
756 break;
757
758 case ErrorCode:
759 if (!mHasErrorCode)
760 {
761 if (attrLen - 4 > MAX_ERRORCODE_REASON_BYTES)
762 {
763 WarningLog(<< "ErrorCode reason length=" << attrLen - 4 << " is longer than max allowed=" << MAX_ERRORCODE_REASON_BYTES);
764 return false;
765 }
766 mHasErrorCode = true;
767 if (stunParseAtrError(body, attrLen, mErrorCode) == false)
768 {
769 WarningLog(<< "problem parsing ErrorCode");
770 return false;
771 }
772 StackLog(<< "ErrorCode = " << (int(mErrorCode.errorClass) * 100 + int(mErrorCode.number))
773 << " (" << *mErrorCode.reason << ")");
774 }
775 else
776 {
777 WarningLog(<< "Duplicate ErrorCode in message - ignoring.");
778 }
779 break;
780
781 case UnknownAttribute:
783 {
785 if (stunParseAtrUnknown(body, attrLen, mUnknownAttributes) == false)
786 {
787 WarningLog(<< "problem parsing UnknownAttribute");
788 return false;
789 }
790 // TODO output
791 }
792 else
793 {
794 WarningLog(<< "Duplicate UnknownAttribute in message - ignoring.");
795 }
796 break;
797
798 case ReflectedFrom: // deprecated
800 {
801 mHasReflectedFrom = true;
802 if (stunParseAtrAddress(body, attrLen, mReflectedFrom) == false)
803 {
804 WarningLog(<< "problem parsing ReflectedFrom");
805 return false;
806 }
807 StackLog(<< "ReflectedFrom = " << mReflectedFrom);
808 }
809 else
810 {
811 WarningLog(<< "Duplicate ReflectedFrom in message - ignoring.");
812 }
813 break;
814
815 case Realm:
816 if (!mHasRealm)
817 {
818 if (attrLen > MAX_REALM_BYTES)
819 {
820 WarningLog(<< "Realm length=" << attrLen << " is longer than max allowed=" << MAX_REALM_BYTES);
821 return false;
822 }
823 mHasRealm = true;
824 mRealm = new resip::Data(resip::Data::Share, body, attrLen);
825 StackLog(<< "Realm = " << *mRealm);
826 }
827 else
828 {
829 WarningLog(<< "Duplicate Realm in message - ignoring.");
830 }
831 break;
832
833 case Nonce:
834 if (!mHasNonce)
835 {
836 if (attrLen > MAX_NONCE_BYTES)
837 {
838 WarningLog(<< "Nonce length=" << attrLen << " is longer than max allowed=" << MAX_NONCE_BYTES);
839 return false;
840 }
841 mHasNonce = true;
842 mNonce = new resip::Data(resip::Data::Share, body, attrLen);
843 StackLog(<< "Nonce = " << *mNonce);
844 }
845 else
846 {
847 WarningLog(<< "Duplicate Nonce in message - ignoring.");
848 }
849 break;
850
852 case XorMappedAddress:
854 {
856 if (stunParseAtrXorAddress(body, attrLen, mXorMappedAddress) == false)
857 {
858 WarningLog(<< "problem parsing XorMappedAddress");
859 return false;
860 }
861 StackLog(<< "XorMappedAddress = " << mXorMappedAddress);
862 }
863 else
864 {
865 WarningLog(<< "Duplicate XorMappedAddress in message - ignoring.");
866 }
867 break;
868
869 case Fingerprint:
870 if (!mHasFingerprint)
871 {
872 mHasFingerprint = true;
873 if (stunParseAtrUInt32(body, attrLen, mFingerprint) == false)
874 {
875 WarningLog(<< "problem parsing Fingerprint");
876 return false;
877 }
878 StackLog(<< "Fingerprint = " << mFingerprint);
879 }
880 else
881 {
882 WarningLog(<< "Duplicate Fingerprint in message - ignoring.");
883 }
884 break;
885
886 case Software:
887 if (!mHasSoftware)
888 {
889 if (attrLen > MAX_SOFTWARE_BYTES)
890 {
891 WarningLog(<< "Software length=" << attrLen << " is longer than max allowed=" << MAX_SOFTWARE_BYTES);
892 return false;
893 }
894 mHasSoftware = true;
895 mSoftware = new resip::Data(resip::Data::Share, body, attrLen);
896 StackLog(<< "Software = " << *mSoftware);
897 }
898 else
899 {
900 WarningLog(<< "Duplicate Software in message - ignoring.");
901 }
902 break;
903
904 case AlternateServer:
906 {
907 mHasAlternateServer = true;
908 if (stunParseAtrAddress(body, attrLen, mAlternateServer) == false)
909 {
910 WarningLog(<< "problem parsing AlternateServer");
911 return false;
912 }
913 StackLog(<< "AlternateServer = " << mAlternateServer);
914 }
915 else
916 {
917 WarningLog(<< "Duplicate AlternateServer in message - ignoring.");
918 }
919 break;
920
921 case SecondaryAddress:
923 {
925 if (stunParseAtrAddress(body, attrLen, mSecondaryAddress) == false)
926 {
927 WarningLog(<< "problem parsing secondaryAddress");
928 return false;
929 }
930 StackLog(<< "SecondaryAddress = " << mSecondaryAddress);
931 }
932 else
933 {
934 WarningLog(<< "Duplicate SecondaryAddress in message - ignoring.");
935 }
936 break;
937
938 // TURN attributes
939
942 {
943 uint32_t channelNumber;
945 if (stunParseAtrUInt32(body, attrLen, channelNumber) == false)
946 {
947 WarningLog(<< "problem parsing channel number");
948 return false;
949 }
950 mTurnChannelNumber = (channelNumber & 0xFFFF0000) >> 16;
951 StackLog(<< "Turn ChannelNumber = " << mTurnChannelNumber);
952 }
953 else
954 {
955 WarningLog(<< "Duplicate TurnChannelNumber in message - ignoring.");
956 }
957 break;
958
959 case TurnLifetime:
960 if (!mHasTurnLifetime)
961 {
962 mHasTurnLifetime = true;
963 if (stunParseAtrUInt32(body, attrLen, mTurnLifetime) == false)
964 {
965 WarningLog(<< "problem parsing turn lifetime");
966 return false;
967 }
968 StackLog(<< "Turn Lifetime = " << mTurnLifetime);
969 }
970 else
971 {
972 WarningLog(<< "Duplicate TurnLifetime in message - ignoring.");
973 }
974 break;
975
976 case TurnBandwidth:
978 {
979 mHasTurnBandwidth = true;
980 if (stunParseAtrUInt32(body, attrLen, mTurnBandwidth) == false)
981 {
982 WarningLog(<< "problem parsing turn bandwidth");
983 return false;
984 }
985 StackLog(<< "Turn Bandwidth = " << mTurnBandwidth);
986 }
987 else
988 {
989 WarningLog(<< "Duplicate TurnBandwidth in message - ignoring.");
990 }
991 break;
992
995 {
996 if (stunParseAtrXorAddress(body, attrLen, mTurnXorPeerAddress[mCntTurnXorPeerAddress]) == false)
997 {
998 WarningLog(<< "problem parsing turn peer address");
999 return false;
1000 }
1001 StackLog(<< "Turn Peer Address = " << mTurnXorPeerAddress[mCntTurnXorPeerAddress]);
1003 }
1004 else
1005 {
1006 WarningLog(<< "Duplicate TurnXorPeerAddress in message - ignoring.");
1007 }
1008 break;
1009
1010 //overlay on parse, ownership is buffer parsed from
1011 case TurnData:
1012 if (!mHasTurnData)
1013 {
1014 mHasTurnData = true;
1015 mTurnData = new resip::Data(resip::Data::Share, body, attrLen);
1016 }
1017 else
1018 {
1019 WarningLog(<< "Duplicate TurnData in message - ignoring.");
1020 }
1021 break;
1022
1025 {
1027 if (stunParseAtrXorAddress(body, attrLen, mTurnXorRelayedAddress) == false)
1028 {
1029 WarningLog(<< "problem parsing turn relay address");
1030 return false;
1031 }
1032 StackLog(<< "Turn Relayed Address = " << mTurnXorRelayedAddress);
1033 }
1034 else
1035 {
1036 WarningLog(<< "Duplicate TurnXorRelayedAddress in message - ignoring.");
1037 }
1038 break;
1039
1040 case TurnEvenPort:
1041 if (!mHasTurnEvenPort)
1042 {
1043 mHasTurnEvenPort = true;
1044 if (stunParseAtrEvenPort(body, attrLen, mTurnEvenPort) == false)
1045 {
1046 WarningLog(<< "problem parsing turn even port");
1047 return false;
1048 }
1049 StackLog(<< "Turn Even Port = " << (int)mTurnEvenPort.propType);
1050 }
1051 else
1052 {
1053 WarningLog(<< "Duplicate TurnEvenPort in message - ignoring.");
1054 }
1055 break;
1056
1059 {
1061 uint32_t requestedTransport;
1062 if (stunParseAtrUInt32(body, attrLen, requestedTransport) == false)
1063 {
1064 WarningLog(<< "problem parsing turn requested transport");
1065 return false;
1066 }
1067 mTurnRequestedTransport = requestedTransport >> 24;
1068 StackLog(<< "Turn Requested Transport = " << (int)mTurnRequestedTransport);
1069 }
1070 else
1071 {
1072 WarningLog(<< "Duplicate TurnRequestedTransport in message - ignoring.");
1073 }
1074 break;
1075
1076 case TurnDontFragment:
1078 {
1079 mHasTurnDontFragment = true;
1080 if (attrLen != 0)
1081 {
1082 WarningLog(<< "invalid attribute length for DontFragment attribute");
1083 return false;
1084 }
1085 StackLog(<< "Turn Dont Fragement = <exists>");
1086 }
1087 else
1088 {
1089 WarningLog(<< "Duplicate TurnDontFragment in message - ignoring.");
1090 }
1091 break;
1092
1095 {
1097 if (stunParseAtrUInt64(body, attrLen, mTurnReservationToken) == false)
1098 {
1099 WarningLog(<< "problem parsing turn reservation token");
1100 return false;
1101 }
1102 StackLog(<< "Turn Reservation Token = " << mTurnReservationToken);
1103 }
1104 else
1105 {
1106 WarningLog(<< "Duplicate TurnReservationToken in message - ignoring.");
1107 }
1108 break;
1109
1110 case TurnConnectStat:
1112 {
1113 mHasTurnConnectStat = true;
1114 if (stunParseAtrUInt32(body, attrLen, mTurnConnectStat) == false)
1115 {
1116 WarningLog(<< "problem parsing turn connect stat");
1117 return false;
1118 }
1119 StackLog(<< "Turn Connect Stat = " << mTurnConnectStat);
1120 }
1121 else
1122 {
1123 WarningLog(<< "Duplicate TurnConnectStat in message - ignoring.");
1124 }
1125 break;
1126
1127 // ICE attributes
1128 case IcePriority:
1129 if (!mHasIcePriority)
1130 {
1131 mHasIcePriority = true;
1132 if (stunParseAtrUInt32(body, attrLen, mIcePriority) == false)
1133 {
1134 WarningLog(<< "problem parsing ICE priority");
1135 return false;
1136 }
1137 StackLog(<< "Ice Priority = " << mIcePriority);
1138 }
1139 else
1140 {
1141 WarningLog(<< "Duplicate IcePriority in message - ignoring.");
1142 }
1143 break;
1144
1145 case IceUseCandidate:
1147 {
1148 mHasIceUseCandidate = true;
1149 if (attrLen != 0)
1150 {
1151 WarningLog(<< "invalid attribute length for IceUseCandidate attribute");
1152 return false;
1153 }
1154 StackLog(<< "Ice UseCandidate = <exists>");
1155 }
1156 else
1157 {
1158 WarningLog(<< "Duplicate IceUseCandidate in message - ignoring.");
1159 }
1160 break;
1161
1162 case IceControlled:
1163 if (!mHasIceControlled)
1164 {
1165 mHasIceControlled = true;
1166 if (stunParseAtrUInt64(body, attrLen, mIceControlledTieBreaker) == false)
1167 {
1168 WarningLog(<< "problem parsing ICE controlled");
1169 return false;
1170 }
1171 StackLog(<< "Ice controlled = " << mIceControlledTieBreaker);
1172 }
1173 else
1174 {
1175 WarningLog(<< "Duplicate IceControlled in message - ignoring.");
1176 }
1177 break;
1178
1179 case IceControlling:
1180 if (!mHasIceControlling)
1181 {
1182 mHasIceControlling = true;
1183 if (stunParseAtrUInt64(body, attrLen, mIceControllingTieBreaker) == false)
1184 {
1185 WarningLog(<< "problem parsing ICE controlling");
1186 return false;
1187 }
1188 StackLog(<< "Ice controlling = " << mIceControllingTieBreaker);
1189 }
1190 else
1191 {
1192 WarningLog(<< "Duplicate IceControlling in message - ignoring.");
1193 }
1194 break;
1195
1196 default:
1197 if (atrType <= 0x7FFF)
1198 {
1200 {
1202 }
1203 WarningLog(<< "Unknown comprehension required attribute: " << atrType);
1204 }
1205 else
1206 {
1207 InfoLog(<< "Ignoring unknown comprehension optional attribute: " << atrType);
1208 }
1209 }
1210
1211 body += attrLen + attrLenPad;
1212 size -= attrLen + attrLenPad;
1213 }
1214
1215 return true;
1216}
1217
1219operator<< (EncodeStream& strm, const UInt128& r)
1220{
1221 strm << int(r.longpart[0]);
1222 for (int i = 1; i < 4; i++)
1223 {
1224 strm << ':' << int(r.longpart[i]);
1225 }
1226
1227 return strm;
1228}
1229
1231operator<<(EncodeStream& strm, const StunMessage::StunAtrAddress& addr)
1232{
1233 if (addr.family == StunMessage::IPv6Family)
1234 {
1235 asio::ip::address_v6::bytes_type bytes = {};
1236 memcpy(bytes.data(), &addr.addr.ipv6, bytes.size());
1237 asio::ip::address_v6 addrv6(bytes);
1238
1239 strm << "[" << addrv6.to_string() << "]:" << addr.port;
1240 }
1241 else
1242 {
1243 uint32_t ip = addr.addr.ipv4;
1244 strm << ((int)(ip >> 24) & 0xFF) << ".";
1245 strm << ((int)(ip >> 16) & 0xFF) << ".";
1246 strm << ((int)(ip >> 8) & 0xFF) << ".";
1247 strm << ((int)(ip >> 0) & 0xFF);
1248
1249 strm << ":" << addr.port;
1250 }
1251
1252 return strm;
1253}
1254
1256operator<<(EncodeStream& os, const StunMessage::StunMsgHdr& h)
1257{
1258 os << "STUN ";
1259 bool outputMethod = true;
1260
1261 switch (h.msgType & 0x0110)
1262 {
1264 os << "Request: ";
1265 break;
1267 os << "Indication: ";
1268 outputMethod = false;
1269 switch (h.msgType & 0x000F)
1270 {
1272 os << "Send";
1273 break;
1275 os << "Data";
1276 break;
1277 default:
1278 os << "Unknown ind method (" << int(h.msgType & 0x000F) << ")";
1279 break;
1280 }
1281 break;
1283 os << "Success Response: ";
1284 break;
1286 os << "Error Response: ";
1287 break;
1288 default:
1289 os << "Unknown class (" << int(h.msgType & 0x0110) << "): ";
1290 }
1291
1292 if (outputMethod)
1293 {
1294 switch (h.msgType & 0x000F)
1295 {
1297 os << "Bind";
1298 break;
1300 os << "SharedSecret";
1301 break;
1303 os << "Allocate";
1304 break;
1306 os << "Refresh";
1307 break;
1309 os << "CreatePermission";
1310 break;
1312 os << "ChannelBind";
1313 break;
1314 default:
1315 os << "Unknown method (" << int(h.msgType & 0x000F) << ")";
1316 break;
1317 }
1318 }
1319
1320 os << ", id ";
1321
1322 os << std::hex;
1323 for (unsigned int i = 0; i < 4; i++) {
1324 os << static_cast<int>(h.magicCookieAndTid.longpart[i]);
1325 }
1326 os << std::dec;
1327
1328 return os;
1329}
1330
1331char*
1332StunMessage::encode16(char* buf, uint16_t data)
1333{
1334 uint16_t ndata = htons(data);
1335 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(uint16_t));
1336 return buf + sizeof(uint16_t);
1337}
1338
1339char*
1340StunMessage::encode32(char* buf, uint32_t data)
1341{
1342 uint32_t ndata = htonl(data);
1343 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(uint32_t));
1344 return buf + sizeof(uint32_t);
1345}
1346
1347char*
1348StunMessage::encode64(char* buf, const uint64_t data)
1349{
1350 uint64_t ndata = hton64(data);
1351 memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(uint64_t));
1352 return buf + sizeof(uint64_t);
1353}
1354
1355char*
1356StunMessage::encode(char* buf, const char* data, unsigned int length)
1357{
1358 memcpy(buf, data, length);
1359 return buf + length;
1360}
1361
1362char*
1363StunMessage::encodeTurnData(char* ptr, const resip::Data* td)
1364{
1365 uint16_t padsize = (uint16_t)td->size() % 4 == 0 ? 0 : 4 - ((uint16_t)td->size() % 4);
1366
1367 ptr = encode16(ptr, TurnData);
1368 ptr = encode16(ptr, (uint16_t)td->size());
1369 memcpy(ptr, td->data(), td->size());
1370 ptr += td->size();
1371 memset(ptr, 0, padsize); // zero out padded data (note: this is not required by the RFC)
1372 return ptr + padsize;
1373}
1374
1375char*
1376StunMessage::encodeAtrUInt32(char* ptr, uint16_t type, uint32_t value)
1377{
1378 ptr = encode16(ptr, type);
1379 ptr = encode16(ptr, 4);
1380 ptr = encode32(ptr, value);
1381 return ptr;
1382}
1383
1384char*
1385StunMessage::encodeAtrUInt64(char* ptr, uint16_t type, uint64_t value)
1386{
1387 ptr = encode16(ptr, type);
1388 ptr = encode16(ptr, 8);
1389 ptr = encode64(ptr, value);
1390 return ptr;
1391}
1392
1393char*
1394StunMessage::encodeAtrXorAddress(char* ptr, uint16_t type, const StunAtrAddress& atr)
1395{
1396 StunAtrAddress xorAtr;
1397 applyXorToAddress(atr, xorAtr);
1398 return encodeAtrAddress(ptr, type, xorAtr);
1399}
1400
1401char*
1402StunMessage::encodeAtrAddress(char* ptr, uint16_t type, const StunAtrAddress& atr)
1403{
1404 ptr = encode16(ptr, type);
1405 ptr = encode16(ptr, atr.family == IPv6Family ? 20 : 8);
1406 *ptr++ = (uint8_t)0; // pad
1407 *ptr++ = atr.family;
1408 ptr = encode16(ptr, atr.port);
1409 if (atr.family == IPv6Family)
1410 {
1411 // Note: addr.ipv6 is stored in network byte order
1412 memcpy(ptr, &atr.addr.ipv6, sizeof(atr.addr.ipv6));
1413 ptr += sizeof(atr.addr.ipv6);
1414 }
1415 else
1416 {
1417 // Note: addr.ipv4 is stored in host byte order - encode32 will conver to network byte order
1418 ptr = encode32(ptr, atr.addr.ipv4);
1419 }
1420
1421 return ptr;
1422}
1423
1424char*
1425StunMessage::encodeAtrError(char* ptr, const StunAtrError& atr)
1426{
1427 resip_assert(atr.reason);
1428 uint16_t padsize = (unsigned int)atr.reason->size() % 4 == 0 ? 0 : 4 - ((unsigned int)atr.reason->size() % 4);
1429
1430 ptr = encode16(ptr, ErrorCode);
1431 ptr = encode16(ptr, 4 + (uint16_t)atr.reason->size());
1432 ptr = encode16(ptr, 0); // pad
1433 *ptr++ = atr.errorClass & 0x7; // first 3 bits only
1434 *ptr++ = atr.number;
1435 ptr = encode(ptr, atr.reason->data(), (unsigned int)atr.reason->size());
1436 memset(ptr, 0, padsize);
1437 return ptr + padsize;
1438}
1439
1440char*
1441StunMessage::encodeAtrUnknown(char* ptr, const StunAtrUnknown& atr)
1442{
1443 uint16_t padsize = (2 * atr.numAttributes) % 4 == 0 ? 0 : 4 - ((2 * atr.numAttributes) % 4);
1444 ptr = encode16(ptr, UnknownAttribute);
1445 ptr = encode16(ptr, 2 * atr.numAttributes);
1446 for (int i = 0; i < atr.numAttributes; i++)
1447 {
1448 ptr = encode16(ptr, atr.attrType[i]);
1449 }
1450 return ptr + padsize;
1451}
1452
1453char*
1454StunMessage::encodeAtrString(char* ptr, uint16_t type, const Data* atr, uint16_t maxBytes)
1455{
1456 resip_assert(atr);
1457 uint16_t size = atr->size() > maxBytes ? maxBytes : (uint16_t)atr->size();
1458 uint16_t padsize = size % 4 == 0 ? 0 : 4 - (size % 4);
1459
1460 ptr = encode16(ptr, type);
1461 ptr = encode16(ptr, size);
1462 ptr = encode(ptr, atr->data(), size);
1463 memset(ptr, 0, padsize); // zero out padded data (note: this is not required by the RFC)
1464 return ptr + padsize;
1465}
1466
1467char*
1468StunMessage::encodeAtrIntegrity(char* ptr, const StunAtrIntegrity& atr)
1469{
1470 ptr = encode16(ptr, MessageIntegrity);
1471 ptr = encode16(ptr, 20);
1472 ptr = encode(ptr, atr.hash, sizeof(atr.hash));
1473 return ptr;
1474}
1475
1476char*
1477StunMessage::encodeAtrIntegritySha256(char* ptr, const StunAtrIntegritySha256& atr)
1478{
1479 ptr = encode16(ptr, MessageIntegritySha256);
1480 ptr = encode16(ptr, 32);
1481 ptr = encode(ptr, atr.hash, sizeof(atr.hash));
1482 return ptr;
1483}
1484
1485char*
1486StunMessage::encodeAtrEvenPort(char* ptr, const TurnAtrEvenPort& atr)
1487{
1488 ptr = encode16(ptr, TurnEvenPort);
1489 ptr = encode16(ptr, 1);
1490 *ptr++ = atr.propType;
1491 *ptr++ = 0; // pad
1492 ptr = encode16(ptr, 0); // pad
1493 return ptr;
1494}
1495
1496bool
1501
1502unsigned int
1503StunMessage::stunEncodeMessage(char* buf, unsigned int bufLen)
1504{
1505 resip_assert(bufLen >= sizeof(StunMsgHdr));
1506 char* ptr = buf;
1507
1509
1510 ptr = encode16(ptr, mHeader.msgType);
1511 char* lengthp = ptr;
1512 ptr = encode16(ptr, 0);
1513 ptr = encode(ptr, reinterpret_cast<const char*>(&mHeader.id), sizeof(mHeader.id));
1514
1515 StackLog(<< "Encoding stun message: " << mHeader);
1516
1518 {
1519 StackLog(<< "Encoding MappedAddress: " << mMappedAddress);
1520 ptr = encodeAtrAddress(ptr, MappedAddress, mMappedAddress);
1521 }
1523 {
1524 StackLog(<< "Encoding ResponseAddress: " << mResponseAddress);
1525 ptr = encodeAtrAddress(ptr, ResponseAddress, mResponseAddress);
1526 }
1528 {
1529 StackLog(<< "Encoding ChangeRequest: " << mChangeRequest);
1530 ptr = encodeAtrUInt32(ptr, ChangeRequest, mChangeRequest);
1531 }
1533 {
1534 StackLog(<< "Encoding SourceAddress: " << mSourceAddress);
1535 ptr = encodeAtrAddress(ptr, SourceAddress, mSourceAddress);
1536 }
1538 {
1539 StackLog(<< "Encoding ChangedAddress: " << mChangedAddress);
1540 ptr = encodeAtrAddress(ptr, ChangedAddress, mChangedAddress);
1541 }
1542 if (mHasUsername)
1543 {
1544 StackLog(<< "Encoding Username: " << *mUsername);
1545 ptr = encodeAtrString(ptr, Username, mUsername, MAX_USERNAME_BYTES);
1546 }
1547 if (mHasPassword)
1548 {
1549 StackLog(<< "Encoding Password: " << *mPassword);
1550 ptr = encodeAtrString(ptr, Password, mPassword, MAX_PASSWORD_BYTES);
1551 }
1552 if (mHasErrorCode)
1553 {
1554 StackLog(<< "Encoding ErrorCode: "
1555 << int(mErrorCode.errorClass)
1556 << " number=" << int(mErrorCode.number)
1557 << " reason="
1558 << *mErrorCode.reason);
1559
1560 ptr = encodeAtrError(ptr, mErrorCode);
1561 }
1563 {
1564 StackLog(<< "Encoding UnknownAttribute: ???");
1565 ptr = encodeAtrUnknown(ptr, mUnknownAttributes);
1566 }
1568 {
1569 StackLog(<< "Encoding ReflectedFrom: " << mReflectedFrom);
1570 ptr = encodeAtrAddress(ptr, ReflectedFrom, mReflectedFrom);
1571 }
1572 if (mHasRealm)
1573 {
1574 StackLog(<< "Encoding Realm: " << *mRealm);
1575 ptr = encodeAtrString(ptr, Realm, mRealm, MAX_REALM_BYTES);
1576 }
1577 if (mHasNonce)
1578 {
1579 StackLog(<< "Encoding Nonce: " << *mNonce);
1580 ptr = encodeAtrString(ptr, Nonce, mNonce, MAX_NONCE_BYTES);
1581 }
1583 {
1584 StackLog(<< "Encoding XorMappedAddress: " << mXorMappedAddress);
1585 ptr = encodeAtrXorAddress(ptr, XorMappedAddress, mXorMappedAddress);
1586 }
1587 if (mHasSoftware)
1588 {
1589 StackLog(<< "Encoding Software: " << *mSoftware);
1590 ptr = encodeAtrString(ptr, Software, mSoftware, MAX_SOFTWARE_BYTES);
1591 }
1593 {
1594 StackLog(<< "Encoding Alternate Server: " << mAlternateServer);
1595 ptr = encodeAtrAddress(ptr, AlternateServer, mAlternateServer);
1596 }
1598 {
1599 StackLog(<< "Encoding SecondaryAddress: " << mSecondaryAddress);
1600 ptr = encodeAtrAddress(ptr, SecondaryAddress, mSecondaryAddress);
1601 }
1602
1604 {
1605 StackLog(<< "Encoding Turn ChannelNumber: " << mTurnChannelNumber);
1606 ptr = encodeAtrUInt32(ptr, TurnChannelNumber, uint32_t(mTurnChannelNumber << 16));
1607 }
1608 if (mHasTurnLifetime)
1609 {
1610 StackLog(<< "Encoding Turn Lifetime: " << mTurnLifetime);
1611 ptr = encodeAtrUInt32(ptr, TurnLifetime, mTurnLifetime);
1612 }
1614 {
1615 StackLog(<< "Encoding Turn Bandwidth: " << mTurnBandwidth);
1616 ptr = encodeAtrUInt32(ptr, TurnBandwidth, mTurnBandwidth);
1617 }
1618 if (mCntTurnXorPeerAddress > 0)
1619 {
1620 for (int i = 0; i < mCntTurnXorPeerAddress; i++)
1621 {
1622 StackLog(<< "Encoding Turn XorPeerAddress: " << mTurnXorPeerAddress[i]);
1623 ptr = encodeAtrXorAddress(ptr, TurnXorPeerAddress, mTurnXorPeerAddress[i]);
1624 }
1625 }
1626 if (mHasTurnData)
1627 {
1628 StackLog(<< "Encoding TurnData (not shown)");
1629 ptr = encodeTurnData(ptr, mTurnData);
1630 }
1632 {
1633 StackLog(<< "Encoding Turn XorRelayedAddress: " << mTurnXorRelayedAddress);
1634 ptr = encodeAtrXorAddress(ptr, TurnXorRelayedAddress, mTurnXorRelayedAddress);
1635 }
1636 if (mHasTurnEvenPort)
1637 {
1638 StackLog(<< "Encoding Turn EvenPort: " << (int)mTurnEvenPort.propType);
1639 ptr = encodeAtrEvenPort(ptr, mTurnEvenPort);
1640 }
1642 {
1643 StackLog(<< "Encoding Turn RequestedTransport: " << (int)mTurnRequestedTransport);
1644 ptr = encodeAtrUInt32(ptr, TurnRequestedTransport, uint32_t(mTurnRequestedTransport << 24));
1645 }
1647 {
1648 StackLog(<< "Encoding Turn DontFragment: <exists>");
1649 ptr = encode16(ptr, TurnDontFragment);
1650 ptr = encode16(ptr, 0); // 0 attribute length
1651 }
1653 {
1654 StackLog(<< "Encoding Turn ReservationToken: " << mTurnReservationToken);
1655 ptr = encodeAtrUInt64(ptr, TurnReservationToken, mTurnReservationToken);
1656 }
1658 {
1659 StackLog(<< "Encoding Turn Connect Stat: " << mTurnConnectStat);
1660 ptr = encodeAtrUInt32(ptr, TurnConnectStat, mTurnConnectStat);
1661 }
1663 {
1664 StackLog(<< "Encoding Turn RequestedAddressFamily: " << mTurnRequestedAddressFamily);
1665 ptr = encodeAtrUInt32(ptr, TurnRequestedAddressFamily, uint32_t(mTurnRequestedAddressFamily << 16));
1666 }
1667 if (mHasIcePriority)
1668 {
1669 StackLog(<< "Encoding ICE Priority: " << mIcePriority);
1670 ptr = encodeAtrUInt32(ptr, IcePriority, mIcePriority);
1671 }
1673 {
1674 StackLog(<< "Encoding ICE UseCandidate: <exists>");
1675 ptr = encode16(ptr, IceUseCandidate);
1676 ptr = encode16(ptr, 0); // 0 attribute length
1677 }
1679 {
1680 StackLog(<< "Encoding ICE Controlled: " << mIceControlledTieBreaker);
1681 ptr = encodeAtrUInt64(ptr, IceControlled, mIceControlledTieBreaker);
1682 }
1684 {
1685 StackLog(<< "Encoding ICE Controlling: " << mIceControllingTieBreaker);
1686 ptr = encodeAtrUInt64(ptr, IceControlling, mIceControllingTieBreaker);
1687 }
1688
1689 // MESSAGE-INTEGRITY, MESSAGE-INTEGRITY-SHA256 and FINGERPRINT must be the
1690 // last attributes, in that order. Each integrity HMAC is computed with the
1691 // header length field set to cover the message up to and including that
1692 // attribute (but not the ones that follow it), per RFC 8489 sections 14.5-14.7.
1693 // We therefore rewrite the length field immediately before each HMAC/CRC.
1694
1696 {
1697 // Length covers up to and including MESSAGE-INTEGRITY (excludes
1698 // MESSAGE-INTEGRITY-SHA256 and FINGERPRINT).
1699 encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)) + 24); // 4 (hdr) + 20 (value)
1700 int len = (int)(ptr - buf);
1701 StackLog(<< "Adding message integrity: buffer size=" << len << ", hmacKey=" << mHmacKey.hex());
1702 StunAtrIntegrity integrity;
1703 computeHmac(integrity.hash, buf, len, mHmacKey.c_str(), (int)mHmacKey.size());
1704 ptr = encodeAtrIntegrity(ptr, integrity);
1705 }
1706
1707#ifdef USE_SSL
1709 {
1710 // Length covers up to and including MESSAGE-INTEGRITY-SHA256 (which itself
1711 // covers any preceding MESSAGE-INTEGRITY), but excludes FINGERPRINT.
1712 encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)) + 36); // 4 (hdr) + 32 (value)
1713 int len = (int)(ptr - buf);
1714 StackLog(<< "Adding message integrity (SHA256): buffer size=" << len << ", hmacKey=" << mHmacKey.hex());
1715 StunAtrIntegritySha256 integrity;
1716 computeHmacSha256(integrity.hash, buf, len, mHmacKey.c_str(), (int)mHmacKey.size());
1717 ptr = encodeAtrIntegritySha256(ptr, integrity);
1718 }
1719#endif
1720
1721 // Update length to cover the full message, including FINGERPRINT if present.
1722 {
1723 uint16_t msgSize = (uint16_t)(ptr - buf - sizeof(StunMsgHdr));
1724 if (mHasFingerprint) msgSize += 8; // 4 (attribute header) + 4 (attribute value)
1725 encode16(lengthp, msgSize);
1726 }
1727
1728 // add finger print if required
1729 if (mHasFingerprint)
1730 {
1731 StackLog(<< "Calculating fingerprint for data of size " << ptr - buf);
1732 uint32_t fingerprint = crc32_fast(buf, ptr - buf) ^ STUN_CRC_FINAL_XOR;
1733 ptr = encodeAtrUInt32(ptr, Fingerprint, fingerprint);
1734 }
1735
1736 return int(ptr - buf);
1737}
1738
1739unsigned int
1740StunMessage::stunEncodeFramedMessage(char* buf, unsigned int bufLen)
1741{
1742 unsigned short size = (unsigned short)stunEncodeMessage(&buf[4], bufLen - 4);
1743
1744 // Add Frame Header info
1745 buf[0] = 0; // Channel 0 for Stun Messages
1746 buf[1] = 0;
1747 uint16_t frameSize = htons(size);
1748 memcpy(&buf[2], (void*)&frameSize, 2); // size is not needed if udp - but should be harmless
1749 return size + 4;
1750}
1751
1752#ifndef USE_SSL
1753void
1754StunMessage::computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
1755{
1756 // HMAC-SHA1 (RFC 2104) using the bundled Sha1 implementation, for builds
1757 // without OpenSSL.
1758 const int blockSize = 64; // SHA1 block size in bytes
1759
1760 unsigned char paddedKey[blockSize];
1761 memset(paddedKey, 0, sizeof(paddedKey));
1762 if (sizeKey > blockSize)
1763 {
1764 // Keys longer than the block size are first hashed down.
1765 Sha1 keyHash;
1766 keyHash.update(std::string(key, sizeKey));
1767 const Data hashedKey = keyHash.finalBin();
1768 memcpy(paddedKey, hashedKey.data(),
1769 hashedKey.size() < static_cast<size_t>(blockSize) ? hashedKey.size() : blockSize);
1770 }
1771 else if (sizeKey > 0)
1772 {
1773 memcpy(paddedKey, key, sizeKey);
1774 }
1775
1776 unsigned char ipad[blockSize];
1777 unsigned char opad[blockSize];
1778 for (int i = 0; i < blockSize; ++i)
1779 {
1780 ipad[i] = paddedKey[i] ^ 0x36;
1781 opad[i] = paddedKey[i] ^ 0x5c;
1782 }
1783
1784 // inner = SHA1( (key XOR ipad) || message )
1785 Sha1 inner;
1786 inner.update(std::string(reinterpret_cast<const char*>(ipad), blockSize));
1787 inner.update(std::string(input, length));
1788 const Data innerDigest = inner.finalBin();
1789
1790 // hmac = SHA1( (key XOR opad) || inner )
1791 Sha1 outer;
1792 outer.update(std::string(reinterpret_cast<const char*>(opad), blockSize));
1793 outer.update(std::string(innerDigest.data(), innerDigest.size()));
1794 const Data outerDigest = outer.finalBin();
1795
1796 resip_assert(outerDigest.size() == 20);
1797 memcpy(hmac, outerDigest.data(), 20);
1798}
1799#else
1800void
1801StunMessage::computeHmac(char* hmac, const char* input, int length, const char* key, int sizeKey)
1802{
1803 //StackLog(<< "***computeHmac: input='" << Data(input, length).hex() << "', length=" << length << ", key='" << Data(key, sizeKey).hex() << "', keySize=" << sizeKey);
1804
1805 unsigned int resultSize = 20;
1806 HMAC(EVP_sha1(),
1807 key, sizeKey,
1808 reinterpret_cast<const unsigned char*>(input), length,
1809 reinterpret_cast<unsigned char*>(hmac), &resultSize);
1810 resip_assert(resultSize == 20);
1811}
1812#endif
1813
1814#ifdef USE_SSL
1815void
1816StunMessage::computeHmacSha256(char* hmac, const char* input, int length, const char* key, int sizeKey)
1817{
1818 unsigned int resultSize = 32;
1819 HMAC(EVP_sha256(),
1820 key, sizeKey,
1821 reinterpret_cast<const unsigned char*>(input), length,
1822 reinterpret_cast<unsigned char*>(hmac), &resultSize);
1823 resip_assert(resultSize == 32);
1824}
1825#endif
1826
1827void
1829{
1831 time -= (time % 20 * 60); // rounded time - current time modulo 20 minutes
1832 //uint64_t hitime = time >> 32;
1833 //uint64_t lotime = time & 0xFFFFFFFF;
1834
1835 mHasUsername = true;
1836 if (!mUsername)
1837 {
1838 mUsername = new Data;
1839 }
1841
1842 if (mRemoteTuple.getAddress().is_v6())
1843 {
1844 *mUsername = Data(mRemoteTuple.getAddress().to_v6().to_bytes().data(), (Data::size_type)mRemoteTuple.getAddress().to_v6().to_bytes().size()).base64encode() + ":";
1845 }
1846 else
1847 {
1848 *mUsername = Data(mRemoteTuple.getAddress().to_v4().to_bytes().data(), (Data::size_type)mRemoteTuple.getAddress().to_v4().to_bytes().size()).base64encode() + ":";
1849 }
1850 unsigned int port = mRemoteTuple.getPort();
1851 *mUsername += Data((char*)&port, sizeof(unsigned int)).base64encode() + ":";
1852 *mUsername += resip::Random::getCryptoRandomHex(8) + ":"; // 8 bytes, 64 bits of randomness
1853 *mUsername += Data((char*)&time, sizeof(time)).hex() + ":";
1854 char hmac[20] = { 0 };
1855 computeHmac(hmac, mUsername->data(), (int)mUsername->size(), USERNAME_KEY.data(), (int)USERNAME_KEY.size());
1856 *mUsername += Data(hmac, sizeof(hmac)).hex();
1857
1858 resip_assert(mUsername->size() % 4 == 0);
1859
1860 StackLog(<< "computed username=" << *mUsername);
1861
1862 // Compute Password
1863 mHasPassword = true;
1864
1865 if (!mPassword)
1866 {
1867 mPassword = new Data;
1868 }
1871
1872 StackLog(<< "computed password=" << *mPassword);
1873}
1874
1875void
1877{
1878 char hmac[20] = { 0 };
1880 computeHmac(hmac, mUsername->data(), (int)mUsername->size(), PASSWORD_KEY.data(), (int)PASSWORD_KEY.size());
1881 password = Data(hmac, sizeof(hmac)).hex();
1882}
1883
1884void
1886{
1888 resip_assert(mUsername && mUsername->size() >= 92);
1889 resip_assert(mUsername->size() == 92 || mUsername->size() == 108);
1890
1891 if (mUsername->size() > 92) // if over a certain size, then contains IPv6 address
1892 {
1893 Data addressPart(Data::Share, mUsername->data(), 24);
1894 addressPart = addressPart.base64decode();
1895 asio::ip::address_v6::bytes_type bytes;
1896 memcpy(bytes.data(), addressPart.data(), bytes.size());
1897 asio::ip::address_v6 addressv6(bytes);
1898 tuple.setAddress(addressv6);
1899
1900 unsigned int port;
1901 Data portPart(Data::Share, mUsername->data() + 25, 4);
1902 portPart = portPart.base64decode();
1903 memcpy(&port, portPart.data(), sizeof(port));
1904 tuple.setPort(port);
1905 }
1906 else
1907 {
1908 Data addressPart(Data::Share, mUsername->data(), 8);
1909 addressPart = addressPart.base64decode();
1910 asio::ip::address_v4::bytes_type bytes;
1911 memcpy(bytes.data(), addressPart.data(), bytes.size());
1912 asio::ip::address_v4 addressv4(bytes);
1913 tuple.setAddress(addressv4);
1914
1915 unsigned int port;
1916 Data portPart(Data::Share, mUsername->data() + 9, 4);
1917 portPart = portPart.base64decode();
1918 memcpy(&port, portPart.data(), sizeof(port));
1919 tuple.setPort(port);
1920 }
1921}
1922
1923void
1924StunMessage::calculateHmacKey(Data& hmacKey, const Data& longtermAuthenticationPassword)
1925{
1927
1928 if (mHasRealm) // Longterm authenicationmode
1929 {
1930 calculateHmacKey(hmacKey, *mUsername, *mRealm, longtermAuthenticationPassword);
1931 }
1932 else
1933 {
1935 }
1936}
1937
1938void
1940{
1942
1943 if (mHasRealm) // Longterm authenicationmode
1944 {
1945 hmacKey = ha1;
1946 }
1947 else
1948 {
1950 }
1951}
1952
1953void
1954StunMessage::calculateHmacKey(Data& hmacKey, const Data& username, const Data& realm, const Data& longtermAuthenticationPassword)
1955{
1956 DigestStream r;
1957 r << username << ":" << realm << ":" << longtermAuthenticationPassword;
1958 hmacKey = r.getBin();
1959
1960 StackLog(<< "calculateHmacKey: '" << username << ":" << realm << ":" << longtermAuthenticationPassword << "' = '" << hmacKey.hex() << "'");
1961}
1962
1963bool
1965{
1967 {
1968 unsigned char hmac[20] = { 0 };
1969
1970 // Store original stun message length from mBuffer
1971 char* lengthposition = (char*)mBuffer.data() + 2;
1972 uint16_t originalLength;
1973 memcpy(&originalLength, lengthposition, 2);
1974
1975 // Update stun message length in mBuffer for calculation
1976 uint16_t tempLength = htons(mMessageIntegrityMsgLength);
1977 memcpy(lengthposition, &tempLength, 2);
1978
1979 // Calculate HMAC
1980 int iHMACBufferSize = mMessageIntegrityMsgLength - 24 /* MessageIntegrity size */ + sizeof(StunMsgHdr); // The entire message proceeding the message integrity attribute
1981 StackLog(<< "Checking message integrity: length=" << mMessageIntegrityMsgLength << ", size=" << iHMACBufferSize << ", hmacKey=" << hmacKey.hex());
1982 computeHmac((char*)hmac, mBuffer.data(), iHMACBufferSize, hmacKey.c_str(), (int)hmacKey.size());
1983
1984 // Restore original stun message length in mBuffer
1985 memcpy(lengthposition, &originalLength, 2);
1986
1987 // Constant-time comparison to avoid leaking the expected HMAC via timing.
1988 unsigned char diff = 0;
1989 for (int i = 0; i < 20; ++i)
1990 {
1991 diff |= static_cast<unsigned char>(mMessageIntegrity.hash[i]) ^ hmac[i];
1992 }
1993 return diff == 0;
1994 }
1995 else
1996 {
1997 // No message integrity attribute present - return true
1998 return true;
1999 }
2000}
2001
2002#ifdef USE_SSL
2003bool
2005{
2007 {
2008 unsigned char hmac[32] = { 0 };
2009
2010 // Store original stun message length from mBuffer
2011 char* lengthposition = (char*)mBuffer.data() + 2;
2012 uint16_t originalLength;
2013 memcpy(&originalLength, lengthposition, 2);
2014
2015 // Update stun message length in mBuffer for calculation
2016 uint16_t tempLength = htons(mMessageIntegritySha256MsgLength);
2017 memcpy(lengthposition, &tempLength, 2);
2018
2019 // Calculate HMAC over the entire message preceding the MESSAGE-INTEGRITY-SHA256 attribute
2020 int iHMACBufferSize = mMessageIntegritySha256MsgLength - 36 /* MessageIntegritySha256 size */ + sizeof(StunMsgHdr);
2021 StackLog(<< "Checking message integrity (SHA256): length=" << mMessageIntegritySha256MsgLength << ", size=" << iHMACBufferSize << ", hmacKey=" << hmacKey.hex());
2022 computeHmacSha256((char*)hmac, mBuffer.data(), iHMACBufferSize, hmacKey.c_str(), (int)hmacKey.size());
2023
2024 // Restore original stun message length in mBuffer
2025 memcpy(lengthposition, &originalLength, 2);
2026
2027 // Constant-time comparison to avoid leaking the expected HMAC via timing.
2028 unsigned char diff = 0;
2029 for (int i = 0; i < 32; ++i)
2030 {
2031 diff |= static_cast<unsigned char>(mMessageIntegritySha256.hash[i]) ^ hmac[i];
2032 }
2033 return diff == 0;
2034 }
2035 else
2036 {
2037 // No message integrity sha256 attribute present - return true
2038 return true;
2039 }
2040}
2041#else
2042bool
2044{
2045 // No SHA-256 implementation is available without OpenSSL; fail rather
2046 // than accept an unverified MESSAGE-INTEGRITY-SHA256 attribute.
2048}
2049#endif
2050
2051bool
2053{
2054 if (mHasFingerprint)
2055 {
2056 StackLog(<< "Calculating fingerprint to check for data of size " << mBuffer.size() - 8);
2057
2058 // Calculate CRC across entire message, except the fingerprint attribute
2059 unsigned long crc_checksum = crc32_fast(mBuffer.data(), mBuffer.size() - 8);
2060 unsigned long crc = crc_checksum ^ STUN_CRC_FINAL_XOR;
2061 if (crc == mFingerprint)
2062 {
2063 return true;
2064 }
2065 else
2066 {
2067 WarningLog(<< "Fingerprint=" << mFingerprint << " does not match CRC=" << crc_checksum);
2068 return false;
2069 }
2070 }
2071 return true;
2072}
2073
2074}
2075
2076
2077/* ====================================================================
2078
2079 Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
2080 Copyright (c) 2007-2008, Plantronics, Inc.
2081 All rights reserved.
2082
2083 Redistribution and use in source and binary forms, with or without
2084 modification, are permitted provided that the following conditions are
2085 met:
2086
2087 1. Redistributions of source code must retain the above copyright
2088 notice, this list of conditions and the following disclaimer.
2089
2090 2. Redistributions in binary form must reproduce the above copyright
2091 notice, this list of conditions and the following disclaimer in the
2092 documentation and/or other materials provided with the distribution.
2093
2094 3. Neither the name of Plantronics nor the names of its contributors
2095 may be used to endorse or promote products derived from this
2096 software without specific prior written permission.
2097
2098 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2099 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2100 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2101 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2102 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2103 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2104 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2105 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2106 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2107 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2108 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2109
2110 ==================================================================== */
uint32_t crc32_fast(const void *data, size_t length, uint32_t previousCrc32)
compute CRC32 using the fastest algorithm for large datasets on modern CPUs
Definition Crc32.cxx:558
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define WarningLog(args_)
Definition Logger.hxx:134
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define STUN_CRC_FINAL_XOR
#define MAX_USERNAME_BYTES
#define MAX_SOFTWARE_BYTES
#define MAX_PASSWORD_BYTES
static const Data PASSWORD_KEY("stunServerPasswordKey")
#define MAX_ERRORCODE_REASON_BYTES
static const Data USERNAME_KEY("stunServerUsernameKey")
#define TURN_MAX_XOR_PEER_ADDR
#define STUN_MAX_UNKNOWN_ATTRIBUTES
Definition Stun.hxx:22
#define MAX_REALM_BYTES
Definition Stun.hxx:58
#define MAX_NONCE_BYTES
Definition Stun.hxx:59
uint64_t mIceControlledTieBreaker
static const uint16_t AlternateServer
static const uint8_t IPv4Family
define stun address families
static const uint16_t StunClassSuccessResponse
static const uint16_t SharedSecretMethod
static const uint16_t BindMethod
uint64_t mIceControllingTieBreaker
StunAtrAddress mMappedAddress
static const uint16_t UnknownAttribute
static const uint16_t TurnBandwidth
bool checkMessageIntegritySha256(const resip::Data &hmacKey)
StunAtrError mErrorCode
static const uint16_t IceUseCandidate
void setTurnData(const char *data, unsigned int len)
void setPassword(const char *password)
uint16_t mMessageIntegritySha256MsgLength
static const uint16_t TurnDontFragment
void createHeader(uint16_t stunclass, uint16_t method)
static const uint16_t XorMappedAddress
StunAtrAddress mSecondaryAddress
void getTupleFromUsername(StunTuple &tuple)
void generateShortTermPasswordForUsername(resip::Data &password)
static const uint16_t MessageIntegritySha256
static const uint16_t Realm
static const uint16_t SecondaryAddress
static const uint16_t TurnSendMethod
StunAtrUnknown mUnknownAttributes
uint64_t mTurnReservationToken
static const uint16_t Username
resip::Data * mUsername
uint8_t mTurnRequestedTransport
StunAtrUnknown mUnknownRequiredAttributes
void applyXorToAddress(const StunAtrAddress &in, StunAtrAddress &out)
resip::Data * mSoftware
uint16_t mMessageIntegrityMsgLength
static const uint16_t XorMappedAddress_old
static const uint16_t TurnReservationToken
uint16_t mTurnRequestedAddressFamily
static const uint16_t TurnEvenPort
static const uint16_t StunClassErrorResponse
resip::Data * mPassword
StunAtrAddress mChangedAddress
static const uint16_t TurnCreatePermissionMethod
void setRealm(const char *realm)
static const uint16_t TurnXorRelayedAddress
unsigned int stunEncodeFramedMessage(char *buf, unsigned int bufLen)
static const uint16_t IcePriority
void setUsername(const char *username)
static const uint16_t TurnData
static const uint16_t Software
static const uint16_t StunClassRequest
static const uint16_t ChangeRequest
StunAtrAddress mTurnXorPeerAddress[TURN_MAX_XOR_PEER_ADDR]
void calculateHmacKey(resip::Data &hmacKey, const resip::Data &longtermAuthenticationPassword)
static const uint16_t TurnAllocateMethod
StunAtrAddress mReflectedFrom
resip::Data * mTurnData
static const uint16_t SourceAddress
StunAtrAddress mXorMappedAddress
bool checkMessageIntegrity(const resip::Data &hmacKey)
void setSoftware(const char *software)
void setErrorCode(unsigned short errorCode, const char *reason)
static const uint16_t MessageIntegrity
static const uint16_t TurnLifetime
StunAtrAddress mAlternateServer
static const uint16_t Fingerprint
StunAtrIntegritySha256 mMessageIntegritySha256
StunMessage & operator=(const StunMessage &rhs)
static const uint16_t Password
static const uint16_t ErrorCode
StunAtrAddress mResponseAddress
static const uint16_t TurnChannelNumber
static const uint16_t TurnDataMethod
static const uint16_t TurnRequestedTransport
StunAtrIntegrity mMessageIntegrity
static const uint16_t TurnXorPeerAddress
resip::Data * mRealm
static void setStunAtrAddressFromTuple(StunAtrAddress &address, const StunTuple &tuple)
static const uint8_t IPv6Family
static const uint32_t StunMagicCookie
unsigned int stunEncodeMessage(char *buf, unsigned int bufLen)
static const uint16_t TurnConnectStat
void calculateHmacKeyForHa1(resip::Data &hmacKey, const resip::Data &ha1)
static const uint16_t MappedAddress
void setNonce(const char *nonce)
static const uint16_t TurnRefreshMethod
static const uint16_t ReflectedFrom
static const uint16_t IceControlled
resip::Data * mNonce
static const uint16_t IceControlling
static const uint16_t Nonce
static const uint16_t TurnRequestedAddressFamily
void setIcePriority(uint32_t priority)
StunAtrAddress mTurnXorRelayedAddress
static const uint16_t TurnChannelBindMethod
StunAtrAddress mSourceAddress
static const uint16_t ResponseAddress
static const uint16_t ChangedAddress
TurnAtrEvenPort mTurnEvenPort
static const uint16_t StunClassIndication
static void setTupleFromStunAtrAddress(StunTuple &tuple, const StunAtrAddress &address)
const asio::ip::address & getAddress() const
Definition StunTuple.hxx:44
unsigned int getPort() const
Definition StunTuple.hxx:47
void setPort(unsigned int port)
Definition StunTuple.hxx:48
void setAddress(const asio::ip::address &address)
Definition StunTuple.hxx:45
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
Definition Data.cxx:2607
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Share
The Data instance will use the buffer in a read-only mode.
Definition Data.hxx:266
Data base64encode(bool useUrlSafe=false) const
Performs RFC 3548 Base 64 encoding of the contents of this data.
Definition Data.cxx:2682
Data & append(const char *str, size_type len)
Appends the specified number of bytes to the end of this Data.
Definition Data.cxx:1058
size_t size_type
Definition Data.hxx:94
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
const char * begin() const noexcept
Returns a pointer to the beginning of the buffer used by the Data.
Definition Data.hxx:642
Data hex() const
Returns a hexadecimal representation of the contents of this Data.
Definition Data.cxx:1577
Data & clear()
Clears the contents of this Data.
Definition Data.hxx:800
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
Used to accumlate data written to the stream in a DigestBuffer and convert the data to Digest.
const Data & getBin()
static int getCryptoRandom()
Definition Random.cxx:330
static Data getCryptoRandomHex(unsigned int numBytes)
Definition Random.cxx:394
resip::Data finalBin()
Definition Sha1.cxx:79
void update(const std::string &s)
Definition Sha1.cxx:33
static uint64_t getTimeSecs()
Returns the current clock time in seconds.
Definition Timer.hxx:78
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
bool operator==(const UInt128 &lhs, const UInt128 &rhs)
bool operator<(const UInt128 &lhs, const UInt128 &rhs)
EncodeStream & operator<<(EncodeStream &strm, const UInt128 &r)
dcm! – add UnusedChecking(_enum) below;
uint64_t ntoh64(const uint64_t input)
Definition compat.hxx:234
uint64_t hton64(const uint64_t input)
Definition compat.hxx:252
#define EncodeStream
unsigned short uint16_t
Definition stdint.h:84
unsigned int uint32_t
Definition stdint.h:85
unsigned char uint8_t
Definition stdint.h:83
unsigned __int64 uint64_t
Definition stdint.h:95
union reTurn::StunMessage::StunAtrAddress::@29 addr
uint16_t attrType[STUN_MAX_UNKNOWN_ATTRIBUTES]
uint32_t longpart[4]
uint8_t errorClass
Definition Stun.hxx:158
char reason[STUN_MAX_STRING]
Definition Stun.hxx:160
uint16_t length
Definition Stun.hxx:134
uint16_t type
Definition Stun.hxx:133
uint16_t attrType[STUN_MAX_UNKNOWN_ATTRIBUTES]
Definition Stun.hxx:166
uint16_t numAttributes
Definition Stun.hxx:167