Stun Server  Compliant with the latest RFCs including 5389, 5769, and 5780
discover the local host's own external IP address
stunreader.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 John Selbie
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 
18 
19 #include "commonincludes.hpp"
20 
21 #include "stunreader.h"
22 #include "stunutils.h"
23 #include "socketaddress.h"
24 #include <boost/crc.hpp>
25 
26 #ifndef __APPLE__
27 #include <openssl/evp.h>
28 #include <openssl/hmac.h>
29 #include <openssl/md5.h>
30 #else
31 #define COMMON_DIGEST_FOR_OPENSSL
32 #include <CommonCrypto/CommonCrypto.h>
33 #endif
34 
35 #include "stunauth.h"
36 #include "fasthash.h"
37 
38 
39 
40 
41 
43 {
44  Reset();
45 }
46 
48 {
49  _fAllowLegacyFormat = true;
53 
54  _indexFingerprint = -1;
56  _countAttributes = 0;
57 
58  memset(&_transactionid, '\0', sizeof(_transactionid));
59  _msgTypeNormalized = 0xffff;
61  _msgLength = 0;
62  _stream.Reset();
63 }
64 
65 
66 void CStunMessageReader::SetAllowLegacyFormat(bool fAllowLegacyFormat)
67 {
68  _fAllowLegacyFormat = fAllowLegacyFormat;
69 }
70 
72 {
74 }
75 
77 {
78  size_t currentSize = _stream.GetSize();
79  switch (_state)
80  {
81  case HeaderNotRead:
82  BOOST_ASSERT(STUN_HEADER_SIZE > currentSize);
83  return STUN_HEADER_SIZE - currentSize;
84  case HeaderValidated:
85  BOOST_ASSERT((_msgLength+STUN_HEADER_SIZE) > currentSize);
86  return (_msgLength+STUN_HEADER_SIZE) - currentSize;
87  default:
88  return 0;
89  }
90  return 0;
91 }
92 
94 {
96  return (pAttrib != NULL);
97 }
98 
100 {
101  HRESULT hr = S_OK;
103  CRefCountedBuffer spBuffer;
104  size_t size=0;
105  boost::crc_32_type crc;
106  uint32_t computedValue=1;
107  uint32_t readValue=0;
108  uint8_t* ptr = NULL;
109 
110 
111  // the fingerprint attribute MUST be the last attribute in the stream.
112  // If it's not, then the code below will return false
113 
114  ChkIf(pAttrib==NULL, E_FAIL);
115 
117 
118  ChkIf(pAttrib->size != 4, E_FAIL);
120  Chk(_stream.GetBuffer(&spBuffer));
121 
122  size = _stream.GetSize();
123  ChkIf(size < STUN_HEADER_SIZE, E_FAIL);
124 
125  ptr = spBuffer->GetData();
126  ChkIfA(ptr==NULL, E_FAIL);
127 
128  crc.process_bytes(ptr, size-8); // -8 because we're assuming the fingerprint attribute is 8 bytes and is the last attribute in the stream
129  computedValue = crc.checksum();
130  computedValue = computedValue ^ STUN_FINGERPRINT_XOR;
131 
132  readValue = *(uint32_t*)(ptr+pAttrib->offset);
133  readValue = ntohl(readValue);
134  hr = (readValue==computedValue) ? S_OK : E_FAIL;
135 
136 Cleanup:
137  return (SUCCEEDED(hr));
138 }
139 
141 {
143 }
144 
146 {
147  HRESULT hr = S_OK;
148 
149  int lastAttributeIndex = _countAttributes - 1;
150  bool fFingerprintAdjustment = false;
151  bool fNoOtherAttributesAfterIntegrity = false;
152  const size_t c_hmacsize = 20;
153  uint8_t hmaccomputed[c_hmacsize] = {}; // zero-init
154  unsigned int hmaclength = c_hmacsize;
155 #ifndef __APPLE__
156  HMAC_CTX ctx = {};
157 #else
158  CCHmacContext ctx = {};
159  UNREFERENCED_VARIABLE(hmaclength);
160 #endif
161  uint32_t chunk32;
162  uint16_t chunk16;
163  size_t len, nChunks;
164  CDataStream stream;
165  CRefCountedBuffer spBuffer;
166  StunAttribute* pAttribIntegrity=NULL;
167 
168  int cmp = 0;
169  bool fContextInit = false;
170 
171 
173 
174  ChkIf(_countAttributes == 0, E_FAIL); // if there's not attributes, there's definitely not a message integrity attribute
176 
177  // can a key be empty?
178  ChkIfA(key==NULL, E_INVALIDARG);
179  ChkIfA(keylength==0, E_INVALIDARG);
180 
182 
183  ChkIf(pAttribIntegrity == NULL, E_FAIL);
184 
185  ChkIf(pAttribIntegrity->size != c_hmacsize, E_FAIL);
186 
187  // first, check to make sure that no other attributes (other than fingerprint) follow the message integrity
188  fNoOtherAttributesAfterIntegrity = (_indexMessageIntegrity == lastAttributeIndex) || ((_indexMessageIntegrity == (lastAttributeIndex-1)) && (_indexFingerprint == lastAttributeIndex));
189  ChkIf(fNoOtherAttributesAfterIntegrity==false, E_FAIL);
190 
191  fFingerprintAdjustment = (_indexMessageIntegrity == (lastAttributeIndex-1));
192 
193  Chk(GetBuffer(&spBuffer));
194  stream.Attach(spBuffer, false);
195 
196  // Here comes the fun part. If there is a fingerprint attribute, we have to adjust the length header in computing the hash
197 #ifndef __APPLE__
198  HMAC_CTX_init(&ctx);
199  HMAC_Init(&ctx, key, keylength, EVP_sha1());
200 #else
201  CCHmacInit(&ctx, kCCHmacAlgSHA1, key, keylength);
202 #endif
203  fContextInit = true;
204 
205  // message type
206  Chk(stream.ReadUint16(&chunk16));
207 #ifndef __APPLE__
208  HMAC_Update(&ctx, (unsigned char*)&chunk16, sizeof(chunk16));
209 #else
210  CCHmacUpdate(&ctx, &chunk16, sizeof(chunk16));
211 #endif
212 
213  // message length
214  Chk(stream.ReadUint16(&chunk16));
215  if (fFingerprintAdjustment)
216  {
217  // subtract the length of the fingerprint off the length header
218  // fingerprint attribute is 8 bytes long including it's own header
219  // and to do this, we have to fix the network byte ordering issue
220  uint16_t lengthHeader = ntohs(chunk16);
221  uint16_t adjustedlengthHeader = lengthHeader - 8;
222 
223 
224  chunk16 = htons(adjustedlengthHeader);
225  }
226 
227 #ifndef __APPLE__
228  HMAC_Update(&ctx, (unsigned char*)&chunk16, sizeof(chunk16));
229 #else
230  CCHmacUpdate(&ctx, &chunk16, sizeof(chunk16));
231 #endif
232 
233  // now include everything up to the hash attribute itself.
234  len = pAttribIntegrity->offset;
235  len -= 4; // subtract the size of the attribute header
236  len -= 4; // subtract the size of the message header (not including the transaction id)
237 
238  // len should be the number of bytes from the start of the transaction ID up through to the start of the integrity attribute header
239  // the stun message has to be a multiple of 4 bytes, so we can read in 32 bit chunks
240  nChunks = len / 4;
241  ASSERT((len % 4) == 0);
242  for (size_t count = 0; count < nChunks; count++)
243  {
244  Chk(stream.ReadUint32(&chunk32));
245 #ifndef __APPLE__
246  HMAC_Update(&ctx, (unsigned char*)&chunk32, sizeof(chunk32));
247 #else
248  CCHmacUpdate(&ctx, &chunk32, sizeof(chunk32));
249 #endif
250  }
251 
252 #ifndef __APPLE__
253  HMAC_Final(&ctx, hmaccomputed, &hmaclength);
254 #else
255  CCHmacFinal(&ctx, hmaccomputed);
256 #endif
257 
258 
259  // now compare the bytes
260  cmp = memcmp(hmaccomputed, spBuffer->GetData() + pAttribIntegrity->offset, c_hmacsize);
261 
262  hr = (cmp == 0 ? S_OK : E_FAIL);
263 
264 Cleanup:
265  if (fContextInit)
266  {
267 #ifndef __APPLE__
268  HMAC_CTX_cleanup(&ctx);
269 #else
270  UNREFERENCED_VARIABLE(fContextInit);
271 #endif
272  }
273 
274  return hr;
275 }
276 
278 {
279  return ValidateMessageIntegrity((uint8_t*)pszPassword, strlen(pszPassword));
280 }
281 
282 HRESULT CStunMessageReader::ValidateMessageIntegrityLong(const char* pszUser, const char* pszRealm, const char* pszPassword)
283 {
284  HRESULT hr = S_OK;
285  const size_t MAX_KEY_SIZE = MAX_STUN_AUTH_STRING_SIZE*3 + 2;
286  uint8_t key[MAX_KEY_SIZE + 1]; // long enough for 64-char strings and two semicolons and a null char
287  uint8_t* pData = NULL;
288  uint8_t* pDst = key;
289  size_t totallength = 0;
290 
291  size_t passwordlength = pszPassword ? strlen(pszPassword) : 0;
292  size_t userLength = pszUser ? strlen(pszUser) : 0;
293  size_t realmLength = pszRealm ? strlen(pszRealm) : 0;
294 
295  uint8_t hash[MD5_DIGEST_LENGTH] = {};
296 
298 
299  totallength = userLength + realmLength + passwordlength + 2; // +2 for two semi-colons
300 
301  pData = GetStream().GetDataPointerUnsafe();
302  ChkIfA(pData==NULL, E_FAIL);
303 
304  if (userLength > 0)
305  {
306  memcpy(pDst, pszUser, userLength);
307  pDst += userLength;
308  }
309  *pDst = ':';
310  pDst++;
311 
312 
313  if (realmLength > 0)
314  {
315  memcpy(pDst, pszRealm, realmLength);
316  pDst += realmLength;
317  }
318  *pDst = ':';
319  pDst++;
320 
321  if (passwordlength > 0)
322  {
323  memcpy(pDst, pszPassword, passwordlength);
324  pDst += passwordlength;
325  }
326  *pDst = '0'; // null terminate for debugging (does not get hashed)
327 
328  ASSERT((pDst-key) == totallength);
329 
330 #ifndef __APPLE__
331  ChkIfA(NULL == MD5(key, totallength, hash), E_FAIL);
332 #else
333  CC_MD5(key, totallength, hash);
334 #endif
335 
336 
337 
338  Chk(ValidateMessageIntegrity(hash, ARRAYSIZE(hash)));
339 
340 Cleanup:
341  return hr;
342 }
343 
344 
345 
347 {
348  StunAttribute* pFound = _mapAttributes.LookupValueByIndex((size_t)index);
349 
350  if (pFound == NULL)
351  {
352  return E_FAIL;
353  }
354 
355  if (pAttribute)
356  {
357  *pAttribute = *pFound;
358  }
359  return S_OK;
360 }
361 
363 {
364  StunAttribute* pFound = _mapAttributes.Lookup(attributeType);
365 
366  if (pFound == NULL)
367  {
368  return E_FAIL;
369  }
370 
371  if (pAttribute)
372  {
373  *pAttribute = *pFound;
374  }
375  return S_OK;
376 }
377 
378 
380 {
381  return (int)(this->_mapAttributes.Size());
382 }
383 
385 {
386  StunAttribute* pAttrib = NULL;
387  HRESULT hr = S_OK;
388  uint16_t portNBO;
389  uint8_t *pData = NULL;
390 
391  ChkIfA(pPort == NULL, E_INVALIDARG);
392 
394  ChkIf(pAttrib == NULL, E_FAIL);
395 
397 
398  pData = _stream.GetDataPointerUnsafe();
399  ChkIf(pData==NULL, E_UNEXPECTED);
400 
401  memcpy(&portNBO, pData + pAttrib->offset, STUN_ATTRIBUTE_RESPONSE_PORT_SIZE);
402  *pPort = ntohs(portNBO);
403 Cleanup:
404  return hr;
405 }
406 
408 {
409  HRESULT hr = S_OK;
410  uint8_t *pData = NULL;
411  StunAttribute *pAttrib;
412  uint32_t value = 0;
413 
414  ChkIfA(pChangeRequest == NULL, E_INVALIDARG);
415 
417  ChkIf(pAttrib == NULL, E_FAIL);
418 
420 
421  pData = _stream.GetDataPointerUnsafe();
422  ChkIf(pData==NULL, E_UNEXPECTED);
423 
424  memcpy(&value, pData + pAttrib->offset, STUN_ATTRIBUTE_CHANGEREQUEST_SIZE);
425 
426  value = ntohl(value);
427 
428  pChangeRequest->fChangeIP = !!(value & 0x0004);
429  pChangeRequest->fChangePort = !!(value & 0x0002);
430 
431 Cleanup:
432  if (FAILED(hr) && pChangeRequest)
433  {
434  pChangeRequest->fChangeIP = false;
435  pChangeRequest->fChangePort = false;
436  }
437 
438  return hr;
439 }
440 
441 
443 {
444  HRESULT hr = S_OK;
445  StunAttribute *pAttrib;
446 
447  ChkIfA(pSizePadding == NULL, E_INVALIDARG);
448 
449  *pSizePadding = 0;
450 
452 
453  ChkIf(pAttrib == NULL, E_FAIL);
454 
455  *pSizePadding = pAttrib->size;
456 
457 Cleanup:
458  return hr;
459 }
460 
462 {
463  HRESULT hr = S_OK;
464  uint8_t* ptr = NULL;
465  uint8_t cl = 0;
466  uint8_t num = 0;
467 
468  StunAttribute* pAttrib;
469 
470  ChkIf(pErrorNumber==NULL, E_INVALIDARG);
471 
473  ChkIf(pAttrib == NULL, E_FAIL);
474 
475  // first 21 bits of error-code attribute must be zero.
476  // followed by 3 bits of "class" and 8 bits for the error number modulo 100
477  ptr = _stream.GetDataPointerUnsafe() + pAttrib->offset + 2;
478 
479  cl = *ptr++;
480  cl = cl & 0x07;
481  num = *ptr;
482  *pErrorNumber = cl * 100 + num;
483 
484 Cleanup:
485  return hr;
486 }
487 
488 
490 {
491  HRESULT hr = S_OK;
492  StunAttribute* pAttrib = _mapAttributes.Lookup(attribType);
493  uint8_t *pAddrStart = NULL;
494 
495  ChkIf(pAttrib == NULL, E_FAIL);
496 
497  pAddrStart = _stream.GetDataPointerUnsafe() + pAttrib->offset;
498  Chk(::GetMappedAddress(pAddrStart, pAttrib->size, pAddr));
499 
500 Cleanup:
501  return hr;
502 
503 }
504 
506 {
507  HRESULT hr = S_OK;
509 Cleanup:
510  return hr;
511 }
512 
514 {
515  HRESULT hr = S_OK;
516 
518 
519  if (FAILED(hr))
520  {
521  // look for the legacy changed address attribute that a legacy (RFC 3489) server would send
523  }
524 
525  return hr;
526 }
527 
528 
530 {
531  HRESULT hr = S_OK;
533 
534  if (FAILED(hr))
535  {
536  // this is the vovida compat address attribute
538  }
539 
540  if (SUCCEEDED(hr))
541  {
543  }
544 
545  return hr;
546 }
547 
549 {
550  HRESULT hr = S_OK;
551 
553 
554  if (FAILED(hr))
555  {
556  // look for the legacy address attribute that a legacy (RFC 3489) server would send
558  }
559 
560  return hr;
561 
562 }
563 
564 
565 HRESULT CStunMessageReader::GetStringAttributeByType(uint16_t attributeType, char* pszValue, /*in-out*/ size_t size)
566 {
567  HRESULT hr = S_OK;
568  StunAttribute* pAttrib = _mapAttributes.Lookup(attributeType);
569 
570  ChkIfA(pszValue == NULL, E_INVALIDARG);
571  ChkIf(pAttrib == NULL, E_INVALIDARG);
572 
573  // size needs to be 1 greater than attrib.size so we can properly copy over a null char at the end
574  ChkIf(pAttrib->size >= size, E_INVALIDARG);
575 
576  memcpy(pszValue, _stream.GetDataPointerUnsafe() + pAttrib->offset, pAttrib->size);
577  pszValue[pAttrib->size] = '\0';
578 
579 Cleanup:
580  return hr;
581 }
582 
583 
584 
585 
587 {
588 
589  HRESULT hr = S_OK;
590  bool fHeaderValid = false;
591  uint16_t msgType;
592  uint16_t msgLength;
593  uint32_t cookie;
594  StunTransactionId transID;
595 
596  Chk(_stream.SeekDirect(0));
597  Chk(_stream.ReadUint16(&msgType));
598  Chk(_stream.ReadUint16(&msgLength));
599  Chk(_stream.Read(&transID.id, sizeof(transID.id)));
600 
601  // convert from big endian to native type
602  msgType = ntohs(msgType);
603  msgLength = ntohs(msgLength);
604 
605  memcpy(&cookie, transID.id, 4);
606  cookie = ntohl(cookie);
607 
608  _fMessageIsLegacyFormat = !(cookie == STUN_COOKIE);
609 
610  fHeaderValid = ( (0==(msgType & 0xc000)) && ((msgLength%4)==0) );
611 
612  // if we aren't in legacy format (the default), then the cookie field of the transaction id must be the STUN_COOKIE
613  fHeaderValid = (fHeaderValid && (_fAllowLegacyFormat || !_fMessageIsLegacyFormat));
614 
615  ChkIf(fHeaderValid == false, E_FAIL);
616 
617  _msgTypeNormalized = ( (msgType & 0x000f) | ((msgType & 0x00e0)>>1) | ((msgType & 0x3E00)>>2) );
618  _msgLength = msgLength;
619 
620  _transactionid = transID;
621 
623 
624 
625  if (STUN_IS_REQUEST(msgType))
626  {
628  }
629  else if (STUN_IS_INDICATION(msgType))
630  {
632  }
633  else if (STUN_IS_SUCCESS_RESP(msgType))
634  {
636  }
637  else if (STUN_IS_ERR_RESP(msgType))
638  {
640  }
641  else
642  {
643  // couldn't possibly happen, because msgClass is only two bits
645  ChkA(E_FAIL);
646  }
647 
648 
649 
650 Cleanup:
651  return hr;
652 }
653 
655 {
656  size_t currentSize = _stream.GetSize();
657  size_t bytesConsumed = STUN_HEADER_SIZE;
658  HRESULT hr = S_OK;
659 
661 
662  while (SUCCEEDED(hr) && (bytesConsumed < currentSize))
663  {
664  uint16_t attributeType;
665  uint16_t attributeLength;
666  uint16_t attributeOffset;
667  int paddingLength=0;
668 
669  hr = _stream.ReadUint16(&attributeType);
670 
671  if (SUCCEEDED(hr))
672  {
673  hr = _stream.ReadUint16(&attributeLength);
674  }
675 
676  if (SUCCEEDED(hr))
677  {
678  attributeOffset = _stream.GetPos();
679  attributeType = ntohs(attributeType);
680  attributeLength = ntohs(attributeLength);
681 
682  // todo - if an attribute has no size, it's length is not padded by 4 bytes, right?
683  if (attributeLength % 4)
684  {
685  paddingLength = 4 - attributeLength % 4;
686  }
687 
688  hr = (attributeLength <= MAX_STUN_ATTRIBUTE_SIZE) ? S_OK : E_FAIL;
689  }
690 
691  if (SUCCEEDED(hr))
692  {
693  int result;
694  StunAttribute attrib;
695  attrib.attributeType = attributeType;
696  attrib.size = attributeLength;
697  attrib.offset = attributeOffset;
698 
699  // if we have already read in more attributes than MAX_NUM_ATTRIBUTES, then Insert call will fail (this is how we gate too many attributes)
700  result = _mapAttributes.Insert(attributeType, attrib);
701  hr = (result >= 0) ? S_OK : E_FAIL;
702  }
703 
704  if (SUCCEEDED(hr))
705  {
706 
707  if (attributeType == ::STUN_ATTRIBUTE_FINGERPRINT)
708  {
710  }
711 
712  if (attributeType == ::STUN_ATTRIBUTE_MESSAGEINTEGRITY)
713  {
715  }
716 
718  }
719 
720 
721 
722  if (SUCCEEDED(hr))
723  {
724  hr = _stream.SeekRelative(attributeLength);
725  }
726 
727  // consume the padding
728  if (SUCCEEDED(hr))
729  {
730  if (paddingLength > 0)
731  {
732  hr = _stream.SeekRelative(paddingLength);
733  }
734  }
735 
736  if (SUCCEEDED(hr))
737  {
738  bytesConsumed += sizeof(attributeType) + sizeof(attributeLength) + attributeLength + paddingLength;
739  }
740  }
741 
742  // I don't think we could consume more bytes than stream size, but it's a worthy check to still keep here
743  hr = (bytesConsumed == currentSize) ? S_OK : E_FAIL;
744 
745 Cleanup:
746  return hr;
747 
748 }
749 
751 {
752  HRESULT hr = S_OK;
753  size_t currentSize;
754 
755  if (_state == ParseError)
756  {
757  return ParseError;
758  }
759 
760  if (size == 0)
761  {
762  return _state;
763  }
764 
765  // seek to the end of the stream
767 
768  if (FAILED(_stream.Write(pData, size)))
769  {
770  return ParseError;
771  }
772 
773  currentSize = _stream.GetSize();
774 
775  if (_state == HeaderNotRead)
776  {
777  if (currentSize >= STUN_HEADER_SIZE)
778  {
779  hr = ReadHeader();
780 
782 
783  if (SUCCEEDED(hr) && (_msgLength==0))
784  {
786  }
787  }
788  }
789 
790  if (_state == HeaderValidated)
791  {
792  if (currentSize >= (_msgLength+STUN_HEADER_SIZE))
793  {
794  if (currentSize == (_msgLength+STUN_HEADER_SIZE))
795  {
796  hr = ReadBody();
798  }
799  else
800  {
801  // TOO MANY BYTES FED IN
802  _state = ParseError;
803  }
804  }
805  }
806 
807  if (_state == BodyValidated)
808  {
809  // What? After validating the body, the caller still passes in way too many bytes?
810  if (currentSize > (_msgLength+STUN_HEADER_SIZE))
811  {
812  _state = ParseError;
813  }
814  }
815 
816  return _state;
817 
818 }
819 
821 {
822  return _state;
823 }
824 
826 {
827  if (pTrans)
828  {
829  *pTrans = _transactionid;
830  }
831 }
832 
833 
835 {
836  return _msgClass;
837 }
838 
840 {
841  return _msgTypeNormalized;
842 }
843 
845 {
846  HRESULT hr = S_OK;
847 
848  ChkIf(pRefBuffer == NULL, E_INVALIDARG);
849  Chk(_stream.GetBuffer(pRefBuffer));
850 
851 Cleanup:
852  return hr;
853 }
854 
856 {
857  return _stream;
858 }
859 
const uint32_t MAX_STUN_MESSAGE_SIZE
Definition: stuntypes.h:178
#define S_OK
Definition: hresult.h:46
size_t GetPos()
Definition: datastream.cpp:177
#define ASSERT(expr)
uint16_t offset
Definition: stuntypes.h:112
HRESULT GetAddressHelper(uint16_t attribType, CSocketAddress *pAddr)
Definition: stunreader.cpp:489
HRESULT GetChangeRequest(StunChangeRequestAttribute *pChangeRequest)
Definition: stunreader.cpp:407
CDataStream & GetStream()
Definition: stunreader.cpp:855
uint16_t GetMessageType()
Definition: stunreader.cpp:839
const uint16_t STUN_ATTRIBUTE_ERRORCODE
Definition: stuntypes.h:45
HRESULT GetAttributeByType(uint16_t attributeType, StunAttribute *pAttribute)
Definition: stunreader.cpp:362
const uint16_t STUN_ATTRIBUTE_PADDING
Definition: stuntypes.h:55
HRESULT ValidateMessageIntegrityLong(const char *pszUser, const char *pszRealm, const char *pszPassword)
Definition: stunreader.cpp:282
void Reset()
Definition: datastream.cpp:47
#define Chk(expr)
Definition: chkmacros.h:53
const uint16_t STUN_ATTRIBUTE_RESPONSE_ORIGIN
Definition: stuntypes.h:69
HRESULT SeekRelative(int nOffset)
Definition: datastream.cpp:207
HRESULT Read(void *data, size_t size)
Definition: datastream.cpp:67
ReaderParseState _state
Definition: stunreader.h:47
HRESULT GetBuffer(CRefCountedBuffer *pRefBuffer)
Definition: stunreader.cpp:844
void ApplyStunXorMap(const StunTransactionId &id)
void Reset()
Definition: fasthash.h:239
void GetTransactionId(StunTransactionId *pTransId)
Definition: stunreader.cpp:825
HRESULT GetBuffer(CRefCountedBuffer *pRefCountedBuffer)
Definition: datastream.cpp:213
const uint32_t STUN_COOKIE
Definition: stuntypes.h:165
bool HasFingerprintAttribute()
Definition: stunreader.cpp:93
HRESULT GetMappedAddress(CSocketAddress *pAddress)
Definition: stunreader.cpp:505
StunMessageClass _msgClass
Definition: stunreader.h:63
#define UNREFERENCED_VARIABLE(unrefparam)
#define ARRAYSIZE(arr)
int Insert(const K &key, V &value)
Definition: fasthash.h:284
#define STUN_IS_SUCCESS_RESP(msg_type)
Definition: stuntypes.h:147
const uint16_t STUN_ATTRIBUTE_FINGERPRINT
Definition: stuntypes.h:67
#define ChkIf(expr, hrerror)
Definition: chkmacros.h:63
ReaderParseState AddBytes(const uint8_t *pData, uint32_t size)
Definition: stunreader.cpp:750
#define STUN_IS_INDICATION(msg_type)
Definition: stuntypes.h:146
bool IsMessageLegacyFormat()
Definition: stunreader.cpp:71
HRESULT ReadUint16(uint16_t *pVal)
Definition: datastream.h:59
#define E_UNEXPECTED
Definition: hresult.h:48
V * LookupValueByIndex(size_t index)
Definition: fasthash.h:392
HRESULT GetOtherAddress(CSocketAddress *pAddress)
Definition: stunreader.cpp:513
uint16_t _msgLength
Definition: stunreader.h:64
#define SUCCEEDED(hr)
Definition: hresult.h:28
const uint16_t STUN_ATTRIBUTE_CHANGEREQUEST
Definition: stuntypes.h:35
const uint16_t STUN_ATTRIBUTE_XORMAPPEDADDRESS
Definition: stuntypes.h:53
const uint32_t MAX_STUN_AUTH_STRING_SIZE
Definition: stunauth.h:22
CDataStream _stream
Definition: stunreader.h:42
const uint16_t STUN_ATTRIBUTE_RESPONSE_PORT
Definition: stuntypes.h:56
uint16_t _msgTypeNormalized
Definition: stunreader.h:62
ReaderParseState GetState()
Definition: stunreader.cpp:820
uint16_t attributeType
Definition: stuntypes.h:110
const uint16_t STUN_ATTRIBUTE_MAPPEDADDRESS
Definition: stuntypes.h:33
const uint16_t STUN_ATTRIBUTE_RESPONSE_PORT_SIZE
Definition: stuntypes.h:140
V * Lookup(const K &key)
Definition: fasthash.h:351
HRESULT GetErrorCode(uint16_t *pErrorNumber)
Definition: stunreader.cpp:461
HRESULT ValidateMessageIntegrityShort(const char *pszPassword)
Definition: stunreader.cpp:277
int32_t HRESULT
Definition: hresult.h:22
HRESULT GetResponsePort(uint16_t *pPort)
Definition: stunreader.cpp:384
HRESULT GetPaddingAttributeSize(uint16_t *pSizePadding)
Definition: stunreader.cpp:442
StunMessageClass
Definition: stuntypes.h:93
const uint16_t STUN_ATTRIBUTE_CHANGEDADDRESS
Definition: stuntypes.h:37
HRESULT ValidateMessageIntegrity(uint8_t *key, size_t keylength)
Definition: stunreader.cpp:145
#define STUN_IS_REQUEST(msg_type)
Definition: stuntypes.h:145
const uint32_t MAX_STUN_ATTRIBUTE_SIZE
Definition: stuntypes.h:179
uint8_t * GetDataPointerUnsafe()
Definition: datastream.cpp:231
HRESULT Write(const void *data, size_t size)
Definition: datastream.cpp:138
bool IsFingerprintAttributeValid()
Definition: stunreader.cpp:99
const uint16_t STUN_ATTRIBUTE_XORMAPPEDADDRESS_OPTIONAL
Definition: stuntypes.h:62
#define E_INVALIDARG
Definition: hresult.h:51
bool _fMessageIsLegacyFormat
Definition: stunreader.h:45
uint8_t id[STUN_TRANSACTION_ID_LENGTH]
Definition: stuntypes.h:154
HRESULT SeekDirect(size_t pos)
Definition: datastream.cpp:187
#define E_FAIL
Definition: hresult.h:56
StunMessageClass GetMessageClass()
Definition: stunreader.cpp:834
#define FAILED(hr)
Definition: hresult.h:29
const uint16_t STUN_ATTRIBUTE_SOURCEADDRESS
Definition: stuntypes.h:36
#define ChkA(expr)
Definition: chkmacros.h:73
const uint16_t STUN_ATTRIBUTE_CHANGEREQUEST_SIZE
Definition: stuntypes.h:141
size_t Size()
Definition: fasthash.h:269
const uint16_t STUN_ATTRIBUTE_MESSAGEINTEGRITY
Definition: stuntypes.h:44
bool HasMessageIntegrityAttribute()
Definition: stunreader.cpp:140
size_t GetSize()
Definition: datastream.cpp:182
#define STUN_IS_ERR_RESP(msg_type)
Definition: stuntypes.h:148
const uint32_t STUN_FINGERPRINT_XOR
Definition: stuntypes.h:172
HRESULT ReadUint32(uint32_t *pVal)
Definition: datastream.h:60
HRESULT ReadHeader()
Definition: stunreader.cpp:586
boost::shared_ptr< CBuffer > CRefCountedBuffer
Definition: buffer.h:65
void SetAllowLegacyFormat(bool fAllowLegacyFormat)
Definition: stunreader.cpp:66
bool _fAllowLegacyFormat
Definition: stunreader.h:44
HRESULT GetStringAttributeByType(uint16_t attributeType, char *pszValue, size_t size)
Definition: stunreader.cpp:565
StunTransactionId _transactionid
Definition: stunreader.h:61
void Attach(CRefCountedBuffer &buffer, bool fForWriting)
Definition: datastream.cpp:55
AttributeHashTable _mapAttributes
Definition: stunreader.h:53
uint16_t HowManyBytesNeeded()
Definition: stunreader.cpp:76
#define ChkIfA(expr, hrerror)
Definition: chkmacros.h:84
HRESULT GetAttributeByIndex(int index, StunAttribute *pAttribute)
Definition: stunreader.cpp:346
uint16_t size
Definition: stuntypes.h:111
const uint32_t STUN_HEADER_SIZE
Definition: stuntypes.h:176
HRESULT GetXorMappedAddress(CSocketAddress *pAddress)
Definition: stunreader.cpp:529
int _indexMessageIntegrity
Definition: stunreader.h:57
const uint16_t STUN_ATTRIBUTE_OTHER_ADDRESS
Definition: stuntypes.h:70
HRESULT GetResponseOriginAddress(CSocketAddress *pAddress)
Definition: stunreader.cpp:548