source: mediastreamer2/linphone/oRTP/src/stun.c @ 748:daf48a9534be

Last change on this file since 748:daf48a9534be was 748:daf48a9534be, checked in by aymeric <aymeric@…>, 4 years ago

use correct type

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@736 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 77.5 KB
Line 
1 /*
2  The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
3  Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
4
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*/
19
20/* ====================================================================
21 * The Vovida Software License, Version 1.0
22 *
23 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 *
29 * 1. Redistributions of source code must retain the above copyright
30 *    notice, this list of conditions and the following disclaimer.
31 *
32 * 2. Redistributions in binary form must reproduce the above copyright
33 *    notice, this list of conditions and the following disclaimer in
34 *    the documentation and/or other materials provided with the
35 *    distribution.
36 *
37 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
38 *    and "Vovida Open Communication Application Library (VOCAL)" must
39 *    not be used to endorse or promote products derived from this
40 *    software without prior written permission. For written
41 *    permission, please contact vocal@vovida.org.
42 *
43 * 4. Products derived from this software may not be called "VOCAL", nor
44 *    may "VOCAL" appear in their name, without prior written
45 *    permission of Vovida Networks, Inc.
46 *
47 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
48 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
50 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
51 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
52 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
56 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
58 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 * DAMAGE.
60 *
61 * ====================================================================
62 *
63 * This software consists of voluntary contributions made by Vovida
64 * Networks, Inc. and many individuals on behalf of Vovida Networks,
65 * Inc.  For more information on Vovida Networks, Inc., please see
66 * <http://www.vovida.org/>.
67 *
68 */
69
70#ifdef HAVE_CONFIG_H
71#include "ortp-config.h"
72#endif
73
74#ifndef _WIN32_WCE
75#include <errno.h>
76#endif
77
78#include <assert.h>
79
80#if defined(WIN32) || defined(_WIN32_WCE)
81#include <winsock2.h>
82#include <stdlib.h>
83/* #include <io.h> */
84#include <time.h>
85#include <ctype.h> /*for isdigit() */
86#else
87
88#include <stdlib.h>
89#include <unistd.h>
90#include <string.h>
91#include <sys/ioctl.h>
92#include <sys/socket.h>
93#include <sys/time.h>
94#include <sys/types.h>
95#include <arpa/inet.h>
96#include <fcntl.h>
97#include <netdb.h>
98#include <netinet/in.h>
99#include <arpa/nameser.h>
100#include <resolv.h>
101#include <net/if.h>
102
103#endif
104
105
106#if !defined(HAVE_OPENSSL_HMAC_H) || !defined(HAVE_OPENSSL_MD5_H)
107#define NOSSL 1
108#endif
109
110#include "ortp/stun_udp.h"
111#include "ortp/stun.h"
112#include "ortp/ortp.h"
113
114static char *ipaddr(const StunAddress4 *addr)
115{
116   static char tmp[512];
117   struct in_addr inaddr;
118   char *atmp;
119   inaddr.s_addr = htonl(addr->addr);
120   atmp = (char *)inet_ntoa(inaddr);
121   
122   snprintf(tmp, 512, "%s:%i", atmp, addr->port);
123   return tmp;
124}
125
126static bool_t
127stunParseAtrAddress( char* body, unsigned int hdrLen,  StunAtrAddress4 *result )
128{
129   if ( hdrLen != 8 )
130   {
131      ortp_error("stun: hdrLen wrong for Address\n");
132      return FALSE;
133   }
134   result->pad = *body++;
135   result->family = *body++;
136   if (result->family == IPv4Family)
137   {
138      uint16_t nport;
139      uint32_t naddr;
140      memcpy(&nport, body, 2); body+=2;
141      result->ipv4.port = ntohs(nport);
142
143      memcpy(&naddr, body, 4); body+=4;
144      result->ipv4.addr = ntohl(naddr);
145      return TRUE;
146   }
147   else if (result->family == IPv6Family)
148   {
149      ortp_error("stun: ipv6 not supported\n");
150   }
151   else
152   {
153      ortp_error("stun: bad address family: %i\n", result->family);
154   }
155       
156   return FALSE;
157}
158
159static bool_t
160stunParseAtrChangeRequest( char* body, unsigned int hdrLen,  StunAtrChangeRequest *result )
161{
162   if ( hdrLen != 4 )
163   {
164     /* ortp_error("stun: hdr length = %i expecting %i\n",hdrLen, sizeof(result)); */
165               
166      ortp_error("stun: Incorrect size for SA_CHANGEREQUEST");
167      return FALSE;
168   }
169   else
170   {
171      memcpy(&result->value, body, 4);
172      result->value = ntohl(result->value);
173      return TRUE;
174   }
175}
176
177static bool_t
178stunParseAtrError( char* body, unsigned int hdrLen,  StunAtrError *result )
179{
180   if ( hdrLen < 4 || hdrLen >= 128+4)
181   {
182      ortp_error("stun: Incorrect size for SA_ERRORCODE");
183      return FALSE;
184   }
185   else
186   {
187      memcpy(&result->pad, body, 2); body+=2;
188      result->pad = ntohs(result->pad);
189      result->errorClass = *body++;
190      result->number = *body++;
191               
192      result->sizeReason = hdrLen - 4;
193      memcpy(&result->reason, body, result->sizeReason);
194      result->reason[result->sizeReason] = 0;
195      return TRUE;
196   }
197}
198
199static bool_t
200stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown *result )
201{
202   if ( hdrLen >= sizeof(result) )
203   {
204      ortp_error("stun: Incorrect size for SA_UNKNOWNATTRIBUTE");
205      return FALSE;
206   }
207   else
208   {
209      int i;
210      if (hdrLen % 4 != 0) return FALSE;
211      result->numAttributes = hdrLen / 4;
212      for (i=0; i<result->numAttributes; i++)
213      {
214         memcpy(&result->attrType[i], body, 2); body+=2;
215         result->attrType[i] = ntohs(result->attrType[i]);
216      }
217      return TRUE;
218   }
219}
220
221static bool_t
222stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString *result )
223{
224   if ( hdrLen >= STUN_MAX_STRING )
225   {
226      ortp_error("stun: String is too large");
227      return FALSE;
228   }
229   else
230   {
231      result->sizeValue = hdrLen;
232      memcpy(&result->value, body, hdrLen);
233      result->value[hdrLen] = 0;
234      return TRUE;
235   }
236}
237
238
239static bool_t
240stunParseAtrIntegrity( char* body, unsigned int hdrLen,  StunAtrIntegrity *result )
241{
242   if ( hdrLen != 20)
243   {
244      ortp_error("stun: SA_MESSAGEINTEGRITY must be 20 bytes");
245      return FALSE;
246   }
247   else
248   {
249      memcpy(&result->hash, body, hdrLen);
250      return TRUE;
251   }
252}
253
254static bool_t
255turnParseAtrChannelNumber( char* body, unsigned int hdrLen,  TurnAtrChannelNumber *result )
256{
257   if ( hdrLen >= sizeof(result) )
258   {
259      ortp_error("stun: Incorrect size for TA_CHANNELNUMBER");
260      return FALSE;
261   }
262   else
263   {
264      if (hdrLen % 4 != 0) return FALSE;
265      memcpy(&result->channelNumber, body, 2);
266      body+=2;
267      result->channelNumber = ntohs(result->channelNumber);
268      memcpy(&result->rffu, body, 2);
269      body+=2;
270      result->rffu = ntohs(result->rffu);
271      return TRUE;
272   }
273}
274
275static bool_t
276turnParseAtrLifetime( char* body, unsigned int hdrLen,  TurnAtrLifetime *result )
277{
278   if ( hdrLen != sizeof(result) )
279   {
280      ortp_error("stun: Incorrect size for TA_LIFETIME");
281      return FALSE;
282   }
283   else
284   {
285      memcpy(&result->lifetime, body, 4);
286      result->lifetime = ntohl(result->lifetime);
287      return TRUE;
288   }
289}
290
291static bool_t
292turnParseAtrData( char* body, unsigned int hdrLen,  TurnAtrData *result )
293{
294   if ( hdrLen >= 1500 )
295   {
296      ortp_error("stun: Incorrect size for TA_DATA");
297      return FALSE;
298   }
299   else
300   {
301      result->sizeValue = hdrLen;
302      memcpy(&result->value, body, hdrLen);
303      result->value[hdrLen] = 0;
304      return TRUE;
305   }
306}
307
308static bool_t
309turnParseAtrRequestedTransport( char* body, unsigned int hdrLen,  TurnAtrRequestedTransport *result )
310{
311   if ( hdrLen != 4 )
312   {
313      ortp_error("stun: Incorrect size for TA_REQUESTEDTRANSPORT");
314      return FALSE;
315   }
316   result->proto = *body++;
317   result->pad1 = *body++;
318   result->pad2 = *body++;
319   result->pad3 = *body++;
320   return TRUE;
321}
322
323#ifdef ORTP_BIGENDIAN
324#define htonq(n) n
325#define ntohq(n) n
326#else /* little endian */
327static inline uint64_t
328htonq (uint64_t v)
329{
330  return htonl ((uint32_t) (v >> 32))
331    | (uint64_t) htonl ((uint32_t) v) << 32;
332}
333static inline uint64_t
334ntohq (uint64_t v)
335{
336  return ntohl ((uint32_t) (v >> 32))
337    | (uint64_t) ntohl ((uint32_t) v) << 32;
338}
339#endif /* little endian */
340
341static bool_t
342turnParseAtrReservationToken( char* body, unsigned int hdrLen,  TurnAtrReservationToken *result )
343{
344  if ( hdrLen != 8 )
345  {
346    ortp_error("stun: Incorrect size for TA_RESERVATIONTOKEN");
347    return FALSE;
348  }
349  memcpy(&result->value, body, 8);
350  result->value = ntohq(result->value);
351  return TRUE;
352}
353
354static bool_t
355stunParseAtrFingerprint( char* body, unsigned int hdrLen, StunAtrFingerprint *result )
356{
357  if ( hdrLen != 4 )
358  {
359    ortp_error("stun: Incorrect size for SA_FINGERPRINT");
360    return FALSE;
361  }
362
363  memcpy(&result->fingerprint, body, 4);
364  result->fingerprint = ntohl(result->fingerprint);
365  return TRUE;
366}
367
368static bool_t
369iceParseAtrPriority( char* body, unsigned int hdrLen, IceAtrPriority *result )
370{
371  if ( hdrLen != 4 )
372  {
373    ortp_error("stun: Incorrect size for ICEA_PRIORITY");
374    return FALSE;
375  }
376
377  memcpy(&result->priority, body, 4);
378  result->priority = ntohl(result->priority);
379  return TRUE;
380}
381
382static bool_t
383iceParseAtrIceControll( char* body, unsigned int hdrLen, IceAtrIceControll *result )
384{
385  if ( hdrLen != 8 )
386  {
387    ortp_error("stun: Incorrect size for ICEA_ICECONTROLLED/ICEA_ICECONTROLLING");
388    return FALSE;
389  }
390  memcpy(&result->value, body, 8);
391  result->value = ntohq(result->value);
392  return TRUE;
393} 
394
395bool_t
396stunParseMessage( char* buf, unsigned int bufLen, StunMessage *msg)
397{
398   char* body;
399   unsigned int size;
400         ortp_debug("stun: Received stun message: %i bytes\n", bufLen);
401   memset(msg, 0, sizeof(msg));
402       
403   if (sizeof(StunMsgHdr) > bufLen)
404   {
405      ortp_warning("stun: message too short\n");
406      return FALSE;
407   }
408
409   memcpy(&msg->msgHdr, buf, sizeof(StunMsgHdr));
410   msg->msgHdr.msgType = ntohs(msg->msgHdr.msgType);
411   msg->msgHdr.msgLength = ntohs(msg->msgHdr.msgLength);
412
413   if (msg->msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
414   {
415      ortp_warning("stun: Message header length doesn't match message size: %i - %i\n", msg->msgHdr.msgLength, bufLen);
416      return FALSE;
417   }
418
419   body = buf + sizeof(StunMsgHdr);
420   size = msg->msgHdr.msgLength;
421       
422   /*ortp_message("stun: bytes after header = %i\n", size); */
423       
424   while ( size > 0 )
425   {
426      /* !jf! should check that there are enough bytes left in the buffer */
427               
428      StunAtrHdr* attr = (StunAtrHdr*)body; /*reinterpret_cast<StunAtrHdr*>(body);*/
429               
430      unsigned int attrLen = ntohs(attr->length);
431      int atrType = ntohs(attr->type);
432               
433      if ( attrLen+4 > size ) 
434      {
435         ortp_error("stun: claims attribute is larger than size of message (attribute type=%i)\n", atrType);
436         return FALSE;
437      }
438               
439      body += 4; /* skip the length and type in attribute header */
440      size -= 4;
441               
442      if (atrType == SA_MAPPEDADDRESS)
443      {
444            msg->hasMappedAddress = TRUE;
445            if ( stunParseAtrAddress(  body,  attrLen,  &msg->mappedAddress )== FALSE )
446            {
447               ortp_error("stun: problem parsing SA_MAPPEDADDRESS\n");
448               return FALSE;
449            }
450            else
451            {
452               ortp_debug("stun: SA_MAPPEDADDRESS = %s\n", ipaddr(&msg->mappedAddress.ipv4));
453            }
454                                       
455      }
456      else if (atrType == SA_RESPONSEADDRESS)
457      {
458            msg->hasResponseAddress = TRUE;
459            if ( stunParseAtrAddress(  body,  attrLen,  &msg->responseAddress )== FALSE )
460            {
461               ortp_error("stun: problem parsing SA_RESPONSEADDRESS");
462               return FALSE;
463            }
464            else
465            {
466               ortp_debug("stun: SA_RESPONSEADDRESS = %s\n", ipaddr(&msg->responseAddress.ipv4));
467            }
468      }
469      else if (atrType == SA_CHANGEREQUEST)
470      {
471            msg->hasChangeRequest = TRUE;
472            if (stunParseAtrChangeRequest( body, attrLen, &msg->changeRequest) == FALSE)
473            {
474               ortp_error("stun: problem parsing SA_CHANGEREQUEST\n");
475               return FALSE;
476            }
477            else
478            {
479               ortp_debug("stun: SA_CHANGEREQUEST = %i\n", msg->changeRequest.value);
480            }
481      }
482      else if (atrType == SA_SOURCEADDRESS)
483      {
484            msg->hasSourceAddress = TRUE;
485            if ( stunParseAtrAddress(  body,  attrLen,  &msg->sourceAddress )== FALSE )
486            {
487               ortp_error("stun: problem parsing SA_SOURCEADDRESS\n");
488               return FALSE;
489            }
490            else
491            {
492               ortp_debug("stun: SA_SOURCEADDRESS = %s\n", ipaddr(&msg->sourceAddress.ipv4) );
493            }
494      }
495      else if (atrType == SA_CHANGEDADDRESS)
496      {
497            msg->hasChangedAddress = TRUE;
498            if ( stunParseAtrAddress(  body,  attrLen,  &msg->changedAddress )== FALSE )
499            {
500               ortp_error("stun: problem parsing SA_CHANGEDADDRESS\n");
501               return FALSE;
502            }
503            else
504            {
505               ortp_debug("stun: SA_CHANGEDADDRESS = %s\n", ipaddr(&msg->changedAddress.ipv4));
506            }
507      }
508      else if (atrType == SA_USERNAME)
509      {
510            msg->hasUsername = TRUE;
511            if (stunParseAtrString( body, attrLen, &msg->username) == FALSE)
512            {
513               ortp_error("stun: problem parsing SA_USERNAME");
514               return FALSE;
515            }
516            else
517            {
518               ortp_debug("stun: SA_USERNAME = %s\n", msg->username.value );
519            }                                   
520      }
521      else if (atrType == SA_PASSWORD)
522      {
523            msg->hasPassword = TRUE;
524            if (stunParseAtrString( body, attrLen, &msg->password) == FALSE)
525            {
526               ortp_error("stun: problem parsing SA_PASSWORD");
527               return FALSE;
528            }
529            else
530            {
531               ortp_debug("stun: SA_PASSWORD = %s\n", msg->password.value );
532            }
533      }
534      else if (atrType == SA_MESSAGEINTEGRITY)
535      {
536            msg->hasMessageIntegrity = TRUE;
537            if (stunParseAtrIntegrity( body, attrLen, &msg->messageIntegrity) == FALSE)
538            {
539               ortp_error("stun: problem parsing SA_MESSAGEINTEGRITY");
540               return FALSE;
541            }                                   
542      }
543      else if (atrType == SA_ERRORCODE)
544      {
545            msg->hasErrorCode = TRUE;
546            if (stunParseAtrError(body, attrLen, &msg->errorCode) == FALSE)
547            {
548               ortp_error("stun: problem parsing SA_ERRORCODE");
549               return FALSE;
550            }
551            else
552            {
553               ortp_debug("stun: SA_ERRORCODE = %i %i %s\n",
554                                   msg->errorCode.errorClass ,
555                                   msg->errorCode.number ,
556                                   msg->errorCode.reason );
557            }
558                                         
559      }
560      else if (atrType == SA_UNKNOWNATTRIBUTE)
561      {
562           msg->hasUnknownAttributes = TRUE;
563            if (stunParseAtrUnknown(body, attrLen, &msg->unknownAttributes) == FALSE)
564            {
565               ortp_error("stun: problem parsing SA_UNKNOWNATTRIBUTE");
566               return FALSE;
567            }
568      }
569      else if (atrType == SA_REFLECTEDFROM)
570      {
571            msg->hasReflectedFrom = TRUE;
572            if ( stunParseAtrAddress(  body,  attrLen,  &msg->reflectedFrom ) == FALSE )
573            {
574               ortp_error("stun: problem parsing SA_REFLECTEDFROM");
575               return FALSE;
576            }
577      }
578      else if (atrType == SA_REALM)
579      {
580            msg->hasRealm = TRUE;
581            if (stunParseAtrString( body, attrLen, &msg->realmName) == FALSE)
582            {
583               ortp_error("stun: problem parsing SA_REALM");
584               return FALSE;
585            }
586            else
587            {
588               ortp_debug("stun: SA_REALM = %s\n", msg->realmName.value );
589            }
590      }
591      else if (atrType == SA_NONCE)
592      {
593            msg->hasNonce = TRUE;
594            if (stunParseAtrString( body, attrLen, &msg->nonceName) == FALSE)
595            {
596               ortp_error("stun: problem parsing SA_NONCE");
597               return FALSE;
598            }
599            else
600            {
601               ortp_debug("stun: SA_NONCE = %s\n", msg->nonceName.value );
602            }
603      }
604      else if (atrType == SA_XORMAPPEDADDRESS || atrType == SA_XORMAPPEDADDRESS2)
605      { 
606           msg->hasXorMappedAddress = TRUE;
607            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorMappedAddress ) == FALSE )
608            {
609               ortp_error("stun: problem parsing SA_XORMAPPEDADDRESS");
610               return FALSE;
611            }
612            else
613            {
614               ortp_debug("stun: SA_XORMAPPEDADDRESS = %s\n", ipaddr(&msg->xorMappedAddress.ipv4) );
615            }
616      }
617      else if (atrType == SA_XORONLY)
618      {
619            ortp_warning("stun: SA_XORONLY - non standard extension ignored\n" );
620      }
621      else if (atrType == SA_SECONDARYADDRESS)
622      {
623            ortp_debug("stun: SA_SECONDARYADDRESS - non standard extension ignored\n" );
624      }
625      else if (atrType == SA_SOFTWARE)
626      {
627            msg->hasSoftware = TRUE;
628            if (stunParseAtrString( body, attrLen, &msg->softwareName) == FALSE)
629            {
630               ortp_error("stun: problem parsing SA_SOFTWARE");
631               return FALSE;
632            }
633            else
634            {
635               ortp_debug("stun: SA_SOFTWARE = %s\n", msg->softwareName.value );
636            }
637      }
638      else if (atrType == TA_CHANNELNUMBER)
639      {
640           msg->hasChannelNumberAttributes = TRUE;
641            if (turnParseAtrChannelNumber(body, attrLen, &msg->channelNumberAttributes) == FALSE)
642            {
643               ortp_error("stun: problem parsing TA_CHANNELNUMBER");
644               return FALSE;
645            }                                   
646      }
647      else if (atrType == TA_LIFETIME)
648      {
649           msg->hasLifetimeAttributes = TRUE;
650            if (turnParseAtrLifetime(body, attrLen, &msg->lifetimeAttributes) == FALSE)
651            {
652               ortp_error("stun: problem parsing TA_LIFETIME");
653               return FALSE;
654            }                                   
655      }
656      else if (atrType == TA_DEPRECATEDBANDWIDTH)
657      {
658           ortp_warning("stun: deprecated attribute TA_DEPRECATEDBANDWIDTH");
659      }
660      else if (atrType == TA_XORPEERADDRESS)
661      {
662            msg->hasXorPeerAddress = TRUE;
663            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorPeerAddress )== FALSE )
664            {
665               ortp_error("stun: problem parsing SA_XORPEERADDRESS\n");
666               return FALSE;
667            }
668            else
669            {
670               ortp_debug("stun: SA_XORPEERADDRESS = %s\n", ipaddr(&msg->xorPeerAddress.ipv4));
671            }
672      }
673      else if (atrType == TA_DATA)
674      {
675            msg->hasData = TRUE;
676            if (turnParseAtrData( body, attrLen, &msg->data) == FALSE)
677            {
678               ortp_error("stun: problem parsing TA_DATA");
679               return FALSE;
680            }
681            else
682            {
683            }
684      }
685      else if (atrType == TA_XORRELAYEDADDRESS)
686      {
687            msg->hasXorRelayedAddress = TRUE;
688            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorRelayedAddress )== FALSE )
689            {
690               ortp_error("stun: problem parsing TA_XORRELAYEDADDRESS\n");
691               return FALSE;
692            }
693            else
694            {
695               ortp_debug("stun: TA_XORRELAYEDADDRESS = %s\n", ipaddr(&msg->xorRelayedAddress.ipv4));
696            }
697      }
698      else if (atrType == TA_EVENPORT)
699      {
700           ortp_warning("stun: do we need this... TA_EVENPORT");
701      }
702      else if (atrType == TA_REQUESTEDTRANSPORT)
703      {
704            msg->hasRequestedTransport = TRUE;
705            if ( turnParseAtrRequestedTransport(  body,  attrLen,  &msg->requestedTransport )== FALSE )
706            {
707               ortp_error("stun: problem parsing TA_REQUESTEDTRANSPORT\n");
708               return FALSE;
709            }
710      }
711      else if (atrType == TA_DONTFRAGMENT)
712      {
713            msg->hasDontFragment = TRUE;
714      }
715      else if (atrType == TA_DEPRECATEDTIMERVAL)
716      {
717           ortp_warning("stun: deprecated attribute TA_DEPRECATEDTIMERVAL");
718      }
719      else if (atrType == TA_RESERVATIONTOKEN)
720      {
721            msg->hasReservationToken = TRUE;
722            if ( turnParseAtrReservationToken(  body,  attrLen,  &msg->reservationToken)== FALSE )
723            {
724               ortp_error("stun: problem parsing TA_RESERVATIONTOKEN\n");
725               return FALSE;
726            }
727      }
728      else if (atrType == SA_FINGERPRINT)
729      {
730            msg->hasFingerprint = TRUE;
731            if ( stunParseAtrFingerprint(  body,  attrLen,  &msg->fingerprint)== FALSE )
732            {
733               ortp_error("stun: problem parsing SA_FINGERPRINT\n");
734               return FALSE;
735            }
736      }
737      else if (atrType == ICEA_PRIORITY)
738      {
739            msg->hasPriority = TRUE;
740            if (iceParseAtrPriority(body, attrLen, &msg->priority) == FALSE)
741            {
742               ortp_error("stun: problem parsing ICEA_PRIORITY");
743               return FALSE;
744            }                                   
745      }
746      else if (atrType == ICEA_USECANDIDATE)
747      {
748            msg->hasUseCandidate = TRUE;
749      }
750      else if (atrType == ICEA_ICECONTROLLED)
751      {
752           msg->hasIceControlled = TRUE;
753           if (iceParseAtrIceControll(body, attrLen, &msg->iceControlled) == FALSE)
754            {
755               ortp_error("stun: problem parsing ICEA_ICECONTROLLED");
756               return FALSE;
757            }
758      }
759      else if (atrType == ICEA_ICECONTROLLING)
760      {
761           msg->hasIceControlling = TRUE;
762           if (iceParseAtrIceControll(body, attrLen, &msg->iceControlling) == FALSE)
763            {
764               ortp_error("stun: problem parsing ICEA_ICECONTROLLING");
765               return FALSE;
766            }
767      }
768      else
769      {
770            if ( atrType <= 0x7FFF ) 
771            {
772              ortp_error("stun: Unknown Comprehension-Required attribute: %04x\n", atrType );
773              return FALSE;
774            }
775            else
776              ortp_warning("stun: Unknown attribute: %04x\n", atrType );
777      }
778               
779      if (attrLen%4>0)
780        attrLen += (4-(attrLen%4));
781     
782      body += attrLen;
783      size -= attrLen;
784   }
785   
786   return TRUE;
787}
788
789
790static char* 
791encode16(char* buf, uint16_t data)
792{
793   uint16_t ndata = htons(data);
794   memcpy(buf, &ndata, sizeof(uint16_t));
795   return buf + sizeof(uint16_t);
796}
797
798static char* 
799encode32(char* buf, uint32_t data)
800{
801   uint32_t ndata = htonl(data);
802   memcpy(buf, &ndata, sizeof(uint32_t));
803   return buf + sizeof(uint32_t);
804}
805
806static char* 
807encode64(char* buf, uint64_t data)
808{
809   uint64_t ndata = htonq(data);
810   memcpy(buf, &ndata, sizeof(uint64_t));
811   return buf + sizeof(uint64_t);
812}
813
814static char* 
815encode(char* buf, const char* data, unsigned int length)
816{
817   memcpy(buf, data, length);
818   return buf + length;
819}
820
821
822static char* 
823encodeAtrAddress4(char* ptr, uint16_t type, const StunAtrAddress4 *atr)
824{
825   ptr = encode16(ptr, type);
826   ptr = encode16(ptr, 8);
827   *ptr++ = atr->pad;
828   *ptr++ = IPv4Family;
829   ptr = encode16(ptr, atr->ipv4.port);
830   ptr = encode32(ptr, atr->ipv4.addr);
831       
832   return ptr;
833}
834
835static char* 
836encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest *atr)
837{
838   ptr = encode16(ptr, SA_CHANGEREQUEST);
839   ptr = encode16(ptr, 4);
840   ptr = encode32(ptr, atr->value);
841   return ptr;
842}
843
844static char* 
845encodeAtrError(char* ptr, const StunAtrError *atr)
846{
847   int padding;
848   int i;
849
850   ptr = encode16(ptr, SA_ERRORCODE);
851   ptr = encode16(ptr, 4 + atr->sizeReason);
852   ptr = encode16(ptr, atr->pad);
853   *ptr++ = atr->errorClass;
854   *ptr++ = atr->number;
855   ptr = encode(ptr, atr->reason, atr->sizeReason);
856
857   padding = (atr->sizeReason+4) % 4;
858   if (padding>0)
859   {
860     for (i=0;i<4-padding;i++)
861     {
862       *ptr++ = 0;
863     }
864   }
865   return ptr;
866}
867
868
869static char* 
870encodeAtrUnknown(char* ptr, const StunAtrUnknown *atr)
871{
872   int i;
873   ptr = encode16(ptr, SA_UNKNOWNATTRIBUTE);
874   ptr = encode16(ptr, 2+2*atr->numAttributes);
875   for (i=0; i<atr->numAttributes; i++)
876   {
877      ptr = encode16(ptr, atr->attrType[i]);
878   }
879   return ptr;
880}
881
882static char* 
883encodeAtrString(char* ptr, uint16_t type, const StunAtrString *atr)
884{
885   int padding;
886   int i;
887       
888   ptr = encode16(ptr, type);
889   ptr = encode16(ptr, atr->sizeValue);
890   ptr = encode(ptr, atr->value, atr->sizeValue);
891
892   padding = atr->sizeValue % 4;
893   if (padding>0)
894   {
895     for (i=0;i<4-padding;i++)
896     {
897       *ptr++ = 0;
898     }
899   }
900   return ptr;
901}
902
903
904static char* 
905encodeAtrIntegrity(char* ptr, const StunAtrIntegrity *atr)
906{
907   ptr = encode16(ptr, SA_MESSAGEINTEGRITY);
908   ptr = encode16(ptr, 20);
909   ptr = encode(ptr, atr->hash, sizeof(atr->hash));
910   return ptr;
911}
912
913static char*
914encodeAtrFingerprint(char* ptr, const StunAtrFingerprint *atr)
915{
916        uint32_t val;
917        ptr = encode16(ptr, SA_FINGERPRINT);
918        ptr = encode16(ptr, 4);
919
920        val = atr->fingerprint;
921        val ^= 0x5354554E;
922        ptr = encode32(ptr, val);
923        return ptr;
924}
925
926static char* 
927encodeAtrRequestedTransport(char* ptr, const TurnAtrRequestedTransport *atr)
928{
929   ptr = encode16(ptr, TA_REQUESTEDTRANSPORT);
930   ptr = encode16(ptr, 4);
931   *ptr++ = atr->proto;
932   *ptr++ = atr->pad1;
933   *ptr++ = atr->pad2;
934   *ptr++ = atr->pad3;
935   return ptr;
936}
937
938static char* 
939encodeAtrLifeTime(char* ptr, const TurnAtrLifetime *atr)
940{
941   ptr = encode16(ptr, TA_LIFETIME);
942   ptr = encode16(ptr, 4);
943   ptr = encode32(ptr, atr->lifetime);
944   return ptr;
945}
946
947static char* 
948encodeAtrDontFragment(char* ptr)
949{
950   ptr = encode16(ptr, TA_DONTFRAGMENT);
951   ptr = encode16(ptr, 0);
952   return ptr;
953}
954
955static char* 
956encodeAtrUseCandidate(char* ptr)
957{
958   ptr = encode16(ptr, ICEA_USECANDIDATE);
959   ptr = encode16(ptr, 0);
960   return ptr;
961}
962
963static char* 
964encodeAtrPriority(char* ptr, const IceAtrPriority *atr)
965{
966   ptr = encode16(ptr, ICEA_PRIORITY);
967   ptr = encode16(ptr, 4);
968   ptr = encode32(ptr, atr->priority);
969   return ptr;
970}
971
972static char* 
973encodeAtrIceControll(char* ptr, uint16_t type, const IceAtrIceControll *atr)
974{
975   ptr = encode16(ptr, type);
976   ptr = encode16(ptr, 8);
977   ptr = encode64(ptr, atr->value);
978   return ptr;
979}
980
981unsigned int
982stunEncodeMessage( const StunMessage *msg, 
983                   char* buf, 
984                   unsigned int bufLen, 
985                   const StunAtrString *password)
986{
987   char* ptr = buf;
988   char* lengthp;
989   ptr = encode16(ptr, msg->msgHdr.msgType);
990   lengthp = ptr;
991   ptr = encode16(ptr, 0);
992   ptr = encode32(ptr, msg->msgHdr.magic_cookie);
993   ptr = encode(ptr, (const char*)msg->msgHdr.tr_id.octet, sizeof(msg->msgHdr.tr_id));
994       
995   ortp_debug("stun: Encoding stun message: ");
996
997   if (msg->hasRequestedTransport)
998   {
999      ortp_debug("stun: Encoding TA_REQUESTEDTRANSPORT: %i\n", msg->requestedTransport.proto );
1000      ptr = encodeAtrRequestedTransport (ptr, &msg->requestedTransport);
1001   }
1002   if (msg->hasLifetimeAttributes)
1003   {
1004      ortp_debug("stun: Encoding TA_LIFETIME: %i\n", msg->lifetimeAttributes.lifetime );
1005      ptr = encodeAtrLifeTime (ptr, &msg->lifetimeAttributes);
1006   }
1007   if (msg->hasDontFragment)
1008   {
1009      ortp_debug("stun: Encoding TA_DONTFRAGMENT: DF\n");
1010      ptr = encodeAtrDontFragment (ptr);
1011   }             
1012   if (msg->hasMappedAddress)
1013   {
1014      ortp_debug("stun: Encoding SA_MAPPEDADDRESS: %s\n", ipaddr(&msg->mappedAddress.ipv4) );
1015      ptr = encodeAtrAddress4 (ptr, SA_MAPPEDADDRESS, &msg->mappedAddress);
1016   }
1017   if (msg->hasResponseAddress)
1018   {
1019      ortp_debug("stun: Encoding SA_RESPONSEADDRESS: %s\n", ipaddr(&msg->responseAddress.ipv4) );
1020      ptr = encodeAtrAddress4(ptr, SA_RESPONSEADDRESS, &msg->responseAddress);
1021   }
1022   if (msg->hasChangeRequest)
1023   {
1024      ortp_debug("stun: Encoding SA_CHANGEREQUEST: %i\n", msg->changeRequest.value );
1025      ptr = encodeAtrChangeRequest(ptr, &msg->changeRequest);
1026   }
1027   if (msg->hasSourceAddress)
1028   {
1029      ortp_debug("stun: Encoding SA_SOURCEADDRESS: %s\n", ipaddr(&msg->sourceAddress.ipv4) );
1030      ptr = encodeAtrAddress4(ptr, SA_SOURCEADDRESS, &msg->sourceAddress);
1031   }
1032   if (msg->hasChangedAddress)
1033   {
1034      ortp_debug("stun: Encoding SA_CHANGEDADDRESS: %s\n", ipaddr(&msg->changedAddress.ipv4) );
1035      ptr = encodeAtrAddress4(ptr, SA_CHANGEDADDRESS, &msg->changedAddress);
1036   }
1037   if (msg->hasUsername)
1038   {
1039      ortp_debug("stun: Encoding SA_USERNAME: %s\n", msg->username.value );
1040      ptr = encodeAtrString(ptr, SA_USERNAME, &msg->username);
1041   }
1042   //if (msg->hasPassword)
1043   //{
1044   //   ortp_debug("stun: Encoding SA_PASSWORD: %s\n", msg->password.value );
1045   //   ptr = encodeAtrString(ptr, SA_PASSWORD, &msg->password);
1046   //}
1047   if (msg->hasErrorCode)
1048   {
1049      ortp_debug("stun: Encoding SA_ERRORCODE: class=%i number=%i reason=%s\n" 
1050                          , msg->errorCode.errorClass
1051                          , msg->errorCode.number
1052                          , msg->errorCode.reason );
1053     
1054      ptr = encodeAtrError(ptr, &msg->errorCode);
1055   }
1056   if (msg->hasUnknownAttributes)
1057   {
1058      ortp_debug("stun: Encoding SA_UNKNOWNATTRIBUTE: ???");
1059      ptr = encodeAtrUnknown(ptr, &msg->unknownAttributes);
1060   }
1061   if (msg->hasReflectedFrom)
1062   {
1063      ortp_debug("stun: Encoding SA_REFLECTEDFROM: %s\n", ipaddr(&msg->reflectedFrom.ipv4) );
1064      ptr = encodeAtrAddress4(ptr, SA_REFLECTEDFROM, &msg->reflectedFrom);
1065   }
1066   if (msg->hasNonce)
1067   {
1068      ortp_debug("stun: Encoding SA_NONCE: %s\n", msg->nonceName.value );
1069      ptr = encodeAtrString(ptr, SA_NONCE, &msg->nonceName);
1070   }
1071   if (msg->hasRealm)
1072   {
1073      ortp_debug("stun: Encoding SA_REALM: %s\n", msg->realmName.value );
1074      ptr = encodeAtrString(ptr, SA_REALM, &msg->realmName);
1075   }
1076   
1077   if (msg->hasXorMappedAddress)
1078   {
1079      ortp_debug("stun: Encoding SA_XORMAPPEDADDRESS: %s\n", ipaddr(&msg->xorMappedAddress.ipv4) );
1080      ptr = encodeAtrAddress4 (ptr, SA_XORMAPPEDADDRESS, &msg->xorMappedAddress);
1081   }
1082   
1083   if (msg->hasPriority)
1084   {       
1085      ortp_debug("stun: Encoding ICEA_PRIORITY\n");
1086      ptr = encodeAtrPriority (ptr, &msg->priority);
1087   }
1088   if (msg->hasUseCandidate)
1089   {       
1090      ortp_debug("stun: Encoding ICEA_USECANDIDATE\n");
1091      ptr = encodeAtrUseCandidate (ptr);
1092   }
1093   if (msg->hasIceControlled)
1094   {       
1095      ortp_debug("stun: Encoding ICEA_ICECONTROLLED\n");
1096      ptr = encodeAtrIceControll (ptr, ICEA_ICECONTROLLED, &msg->iceControlled);
1097   }
1098   if (msg->hasIceControlling)
1099   {       
1100      ortp_debug("stun: Encoding ICEA_ICECONTROLLING\n");
1101      ptr = encodeAtrIceControll (ptr, ICEA_ICECONTROLLING, &msg->iceControlling);
1102   }
1103
1104   if (msg->hasSoftware)
1105   {
1106      ortp_debug("stun: Encoding SA_SOFTWARE: %s\n", msg->softwareName.value );
1107      ptr = encodeAtrString(ptr, SA_SOFTWARE, &msg->softwareName);
1108   }
1109
1110   if (msg->hasMessageIntegrity
1111     &&password!=NULL && password->sizeValue > 0
1112     &&msg->username.sizeValue>0
1113     &&msg->realmName.sizeValue>0)
1114   {
1115      StunAtrIntegrity integrity;
1116      //ortp_debug("stun: HMAC with password: %s\n", password->value );
1117
1118      encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)+24));
1119      stunCalculateIntegrity_longterm(integrity.hash, buf, (int)(ptr-buf) ,
1120        msg->username.value, msg->realmName.value, password->value);
1121      ptr = encodeAtrIntegrity(ptr, &integrity);
1122   }
1123   else if (msg->hasMessageIntegrity
1124     &&password!=NULL && password->sizeValue > 0
1125     &&msg->username.sizeValue>0)
1126   {
1127      StunAtrIntegrity integrity;
1128      //ortp_debug("stun: HMAC with password: %s\n", password->value );
1129
1130      encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)+24));
1131      stunCalculateIntegrity_shortterm(integrity.hash, buf, (int)(ptr-buf) ,
1132        password->value);
1133      ptr = encodeAtrIntegrity(ptr, &integrity);
1134   }
1135
1136   if (msg->hasFingerprint)
1137   {
1138      StunAtrFingerprint fingerprint;
1139      //ortp_debug("stun: HMAC with password: %s\n", password->value );
1140
1141      encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)+8));
1142      fingerprint.fingerprint = stunCalculateFingerprint(buf, (int)(ptr-buf));
1143      ptr = encodeAtrFingerprint(ptr, &fingerprint);
1144   }
1145   encode16(lengthp, (uint16_t)(ptr - buf - sizeof(StunMsgHdr)));
1146   return (int)(ptr - buf);
1147}
1148
1149int 
1150stunRand(void)
1151{
1152   /* return 32 bits of random stuff */
1153   /* assert( sizeof(int) == 4 ); */
1154   static bool_t init=FALSE;
1155   if ( !init )
1156   { 
1157      uint64_t tick;
1158      int seed;
1159      init = TRUE;
1160
1161#if defined(_WIN32_WCE)
1162      tick = GetTickCount ();
1163#elif defined(_MSC_VER)
1164      {
1165      volatile unsigned int lowtick=0,hightick=0;
1166      __asm
1167         {
1168            rdtsc
1169               mov lowtick, eax
1170               mov hightick, edx
1171               }
1172      tick = hightick;
1173      tick <<= 32;
1174      tick |= lowtick;
1175      }
1176#elif defined(__MACH__)
1177           {
1178                   int fd=open("/dev/random",O_RDONLY);
1179                   read(fd,&tick,sizeof(tick));
1180                   closesocket(fd);
1181           }
1182#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) )
1183      asm("rdtsc" : "=A" (tick));
1184#elif defined(__GNUC__) && defined(__amd64__)
1185      asm("rdtsc" : "=A" (tick));
1186#elif defined (__SUNPRO_CC) && defined( __sparc__ )     
1187      tick = gethrtime();
1188#elif defined(__linux) || defined(HAVE_DEV_RANDOM)
1189      {
1190        fd_set fdSet;
1191        int maxFd=0;
1192        struct timeval tv;
1193        int e;
1194
1195        int fd=open("/dev/random",O_RDONLY);
1196
1197        if (fd<0)
1198        {
1199            ortp_message("stun: Failed to open random device\n");
1200            return random();
1201        }
1202        FD_ZERO(&fdSet);
1203        FD_SET(fd,&fdSet);
1204        maxFd=fd+1;
1205
1206        tv.tv_sec = 0;
1207        tv.tv_usec = 500;
1208
1209        e = select( maxFd, &fdSet, NULL,NULL, &tv );
1210        if (e <= 0)
1211        {
1212           ortp_error("stun: Failed to get data from random device\n");
1213           closesocket(fd);
1214           return random();
1215        }
1216        read(fd,&tick,sizeof(tick));
1217        closesocket(fd);
1218      }
1219#else
1220#     error Need some way to seed the random number generator
1221#endif
1222      seed = (int)(tick);
1223#if     defined(_WIN32) || defined(_WIN32_WCE)
1224      srand(seed);
1225#else
1226      srandom(seed);
1227#endif
1228   }
1229       
1230#if     defined(_WIN32) || defined(_WIN32_WCE)
1231   /* assert( RAND_MAX == 0x7fff ); */
1232   {
1233       int r1 = rand();
1234       int r2 = rand();
1235       int ret = (r1<<16) + r2;
1236       
1237       return ret;
1238   }
1239#else
1240   return random(); 
1241#endif
1242}
1243
1244
1245/* return a random number to use as a port */
1246static int
1247randomPort()
1248{
1249   int min=0x4000;
1250   int max=0x7FFF;
1251       
1252   int ret = stunRand();
1253   ret = ret|min;
1254   ret = ret&max;
1255       
1256   return ret;
1257}
1258
1259
1260#ifdef NOSSL
1261void
1262stunCalculateIntegrity_longterm(char* hmac, const char* input, int length,
1263                     const char *username, const char *realm, const char *password)
1264{
1265   strncpy(hmac,"hmac-not-implemented",20);
1266}
1267void
1268stunCalculateIntegrity_shortterm(char* hmac, const char* input, int length, const char* key)
1269{
1270   strncpy(hmac,"hmac-not-implemented",20);
1271}
1272
1273#else
1274#include <openssl/hmac.h>
1275#include <openssl/md5.h>
1276
1277void
1278stunCalculateIntegrity_longterm(char* hmac, const char* input, int length,
1279                     const char *username, const char *realm, const char *password)
1280{
1281   unsigned int resultSize=0;
1282   unsigned char HA1[16];
1283   char HA1_text[1024];
1284
1285   snprintf(HA1_text, sizeof(HA1_text), "%s:%s:%s", username, realm, password);
1286   MD5((unsigned char *)HA1_text, strlen(HA1_text), HA1);
1287
1288   HMAC(EVP_sha1(), 
1289        HA1, 16, 
1290        (const unsigned char*) input, length, 
1291        (unsigned char*)hmac, &resultSize);
1292}
1293
1294void
1295stunCalculateIntegrity_shortterm(char* hmac, const char* input, int length, const char* key)
1296{
1297   unsigned int resultSize=0;
1298   HMAC(EVP_sha1(), 
1299        key, strlen(key), 
1300        (const unsigned char*) input, length, 
1301        (unsigned char*)hmac, &resultSize);
1302}
1303
1304#endif
1305
1306uint32_t
1307stunCalculateFingerprint(const char* input, int length)
1308{
1309        /*-
1310        2  *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
1311        3  *  code or tables extracted from it, as desired without restriction.
1312        4  */
1313        static uint32_t crc32_tab[] = {
1314                0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
1315                0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1316                0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
1317                0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1318                0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1319                0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1320                0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
1321                0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1322                0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
1323                0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1324                0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
1325                0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1326                0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
1327                0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1328                0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1329                0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1330                0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
1331                0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1332                0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
1333                0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1334                0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
1335                0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1336                0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
1337                0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1338                0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1339                0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1340                0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
1341                0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1342                0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
1343                0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1344                0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
1345                0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1346                0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
1347                0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1348                0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1349                0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1350                0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
1351                0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1352                0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
1353                0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1354                0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
1355                0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1356                0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1357        };
1358        const uint8_t *p = (uint8_t*)input;
1359        uint32_t crc;
1360
1361        crc = ~0U;
1362        while (length--)
1363                crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
1364        return crc ^ ~0U;
1365}
1366
1367uint64_t
1368stunGetSystemTimeSecs(void)
1369{
1370   uint64_t time=0;
1371#if     defined(_WIN32) || defined(_WIN32_WCE)
1372   SYSTEMTIME t;
1373   /*  CJ TODO - this probably has bug on wrap around every 24 hours */
1374   GetSystemTime( &t );
1375   time = (t.wHour*60+t.wMinute)*60+t.wSecond; 
1376#else
1377   struct timeval now;
1378   gettimeofday( &now , NULL );
1379   /* assert( now ); */
1380   time = now.tv_sec;
1381#endif
1382   return time;
1383}
1384
1385
1386/* returns TRUE if it scucceeded */
1387bool_t
1388stunParseHostName( const char* peerName,
1389                   uint32_t* ip,
1390                   uint16_t* portVal,
1391                   uint16_t defaultPort )
1392{
1393   struct in_addr sin_addr;
1394   
1395   char host[512];
1396   char* port = NULL;
1397   int portNum = defaultPort;
1398   char* sep;
1399   struct hostent* h;
1400
1401   strncpy(host,peerName,512);
1402   host[512-1]='\0';
1403       
1404   /* pull out the port part if present. */
1405   sep = strchr(host,':');
1406       
1407   if ( sep == NULL )
1408   {
1409      portNum = defaultPort;
1410   }
1411   else
1412   {
1413      char* endPtr=NULL;
1414      *sep = '\0';
1415      port = sep + 1;
1416      /* set port part */
1417     
1418               
1419      portNum = strtol(port,&endPtr,10);
1420               
1421      if ( endPtr != NULL )
1422      {
1423         if ( *endPtr != '\0' )
1424         {
1425            portNum = defaultPort;
1426         }
1427      }
1428   }
1429   
1430   if ( portNum < 1024 ) return FALSE;
1431   if ( portNum >= 0xFFFF ) return FALSE;
1432       
1433   /* figure out the host part */
1434       
1435#if     defined(_WIN32) || defined(_WIN32_WCE)
1436   /* assert( strlen(host) >= 1 ); */
1437   if ( isdigit( host[0] ) )
1438   {
1439      /* assume it is a ip address */
1440      unsigned long a = inet_addr(host);
1441      /* cerr << "a=0x" << hex << a << dec ); */
1442               
1443      *ip = ntohl( a );
1444   }
1445   else
1446   {
1447      /* assume it is a host name */
1448      h = gethostbyname( host );
1449               
1450      if ( h == NULL )
1451      {
1452         /*int err = getErrno();*/
1453
1454         /* ortp_message("stun: error was %i\n", err); */
1455         /* std::cerr << "error was " << err << std::endl; */
1456         /* assert( err != WSANOTINITIALISED ); */
1457                       
1458         *ip = ntohl( 0x7F000001L );
1459                       
1460         return FALSE;
1461      }
1462      else
1463      {
1464         sin_addr = *(struct in_addr*)h->h_addr;
1465         *ip = ntohl( sin_addr.s_addr );
1466      }
1467   }
1468       
1469#else
1470   h = gethostbyname( host );
1471   if ( h == NULL )
1472   {
1473      /*
1474         int err = getErrno();
1475         ortp_message("stun: error was %i\n", err);
1476      */
1477      *ip = ntohl( 0x7F000001L );
1478      return FALSE;
1479   }
1480   else
1481   {
1482      sin_addr = *(struct in_addr*)h->h_addr;
1483      *ip = ntohl( sin_addr.s_addr );
1484   }
1485#endif
1486       
1487   *portVal = portNum;
1488       
1489   return TRUE;
1490}
1491
1492
1493bool_t
1494stunParseServerName( const char* name, StunAddress4 *addr)
1495{
1496   /* assert(name); */
1497       
1498   /* TODO - put in DNS SRV stuff. */
1499       
1500   bool_t ret = stunParseHostName( name, &addr->addr, &addr->port, 3478); 
1501   if ( ret != TRUE ) 
1502   {
1503       addr->port=0xFFFF;
1504   }   
1505   return ret;
1506}
1507
1508
1509static void
1510stunCreateErrorResponse(StunMessage *response, int cl, int number, const char* msg)
1511{
1512   response->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_ERR_RESP);
1513   response->hasErrorCode = TRUE;
1514   response->errorCode.errorClass = cl;
1515   response->errorCode.number = number;
1516   strcpy(response->errorCode.reason, msg);
1517}
1518
1519#if 0
1520static void
1521stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg)
1522{
1523   response.msgHdr.msgType = SharedSecretErrorResponseMsg;
1524   response.hasErrorCode = TRUE;
1525   response.errorCode.errorClass = cl;
1526   response.errorCode.number = number;
1527   strcpy(response.errorCode.reason, msg);
1528}
1529#endif
1530
1531#if 0
1532static void
1533stunCreateSharedSecretResponse(const StunMessage *request, const StunAddress4 *source, StunMessage *response)
1534{
1535   response->msgHdr.msgType = SharedSecretResponseMsg;
1536   response->msgHdr.tr_id = request->msgHdr.tr_id;
1537       
1538   response->hasUsername = TRUE;
1539   stunCreateUserName( source, &response->username);
1540       
1541   response->hasPassword = TRUE;
1542   stunCreatePassword( &response->username, &response->password);
1543}
1544#endif
1545
1546/* This funtion takes a single message sent to a stun server, parses
1547   and constructs an apropriate repsonse - returns TRUE if message is
1548   valid */
1549bool_t
1550stunServerProcessMsg( char* buf,
1551                      unsigned int bufLen,
1552                      StunAddress4 *from, 
1553                      StunAddress4 *myAddr,
1554                      StunAddress4 *altAddr, 
1555                      StunMessage *resp,
1556                      StunAddress4 *destination,
1557                      StunAtrString *hmacPassword,
1558                      bool_t* changePort,
1559                      bool_t* changeIp)
1560{
1561   int i;
1562   StunMessage req;
1563   StunAddress4 mapped;
1564   StunAddress4 respondTo;
1565   uint32_t flags;
1566   bool_t ok;
1567   /* set up information for default response */
1568       
1569   memset( &req, 0 , sizeof(req) );
1570   memset( resp, 0 , sizeof(*resp) );
1571       
1572   *changeIp = FALSE;
1573   *changePort = FALSE;
1574       
1575   ok = stunParseMessage( buf,bufLen, &req);
1576   
1577   if (!ok)      /* Complete garbage, drop it on the floor */
1578   {
1579      ortp_error("stun: Request did not parse");
1580      return FALSE;
1581   }
1582   //ortp_debug("stun: Request parsed ok");
1583       
1584   mapped = req.mappedAddress.ipv4;
1585   respondTo = req.responseAddress.ipv4;
1586   flags = req.changeRequest.value;
1587       
1588   if (req.msgHdr.msgType==(STUN_METHOD_BINDING|STUN_REQUEST))
1589   {
1590         if (!req.hasMessageIntegrity)
1591         {
1592            //ortp_debug("stun: BindRequest does not contain SA_MESSAGEINTEGRITY");
1593                               
1594            if (0) /* !jf! mustAuthenticate */
1595            {
1596               ortp_error("stun: Received BindRequest with no SA_MESSAGEINTEGRITY. Sending 401.");
1597               stunCreateErrorResponse(resp, 4, 1, "Missing SA_MESSAGEINTEGRITY");
1598               return TRUE;
1599            }
1600         }
1601         else
1602         {
1603            if (!req.hasUsername)
1604            {
1605               ortp_error("stun: No UserName. Send 432.");
1606               stunCreateErrorResponse(resp, 4, 32, "No UserName and contains SA_MESSAGEINTEGRITY");
1607               return TRUE;
1608            }
1609            else
1610            {
1611               //ortp_debug("stun: Validating username: %s", req.username.value );
1612               /* !jf! could retrieve associated password from provisioning here */
1613               if (strcmp(req.username.value, "test") == 0)
1614               {
1615                  if (0)
1616                  {
1617                     /* !jf! if the credentials are stale */
1618                     stunCreateErrorResponse(resp, 4, 30, "Stale credentials on BindRequest");
1619                     return TRUE;
1620                  }
1621                  else
1622                  {
1623                     unsigned char hmac[20];
1624                     //ortp_debug("stun: Validating SA_MESSAGEINTEGRITY");
1625                     /* need access to shared secret */
1626
1627#ifndef NOSSL
1628                     {
1629                        unsigned int hmacSize=20;
1630
1631                        HMAC(EVP_sha1(), 
1632                             "1234", 4, 
1633                             (const unsigned char*) buf, bufLen-20-4, 
1634                             hmac, &hmacSize);
1635                     }
1636#endif
1637                                                       
1638                     if (memcmp(buf, hmac, 20) != 0)
1639                     {
1640                        ortp_error("stun: SA_MESSAGEINTEGRITY is bad. Sending ");
1641                        stunCreateErrorResponse(resp, 4, 3, "Unknown username. Try test with password 1234");
1642                        return TRUE;
1643                     }
1644                                                       
1645                     /* need to compute this later after message is filled in */
1646                     resp->hasMessageIntegrity = TRUE;
1647                     /* assert(req.hasUsername); */
1648                     resp->hasUsername = TRUE;
1649                     resp->username = req.username; /* copy username in */
1650                  }
1651               }
1652               else
1653               {
1654                  ortp_error("stun: Invalid username: %s Send 430", req.username.value); 
1655               }
1656            }
1657         }
1658                       
1659         /* TODO !jf! should check for unknown attributes here and send 420 listing the
1660            unknown attributes. */
1661                       
1662         if ( respondTo.port == 0 )
1663         {
1664            /* respondTo = from; */
1665            memcpy(&respondTo, from, sizeof(StunAddress4));
1666         }
1667         if ( mapped.port == 0 ) 
1668         {
1669            /* mapped = from; */
1670            memcpy(&mapped, from, sizeof(StunAddress4));
1671         }
1672
1673         *changeIp   = ( flags & ChangeIpFlag )?TRUE:FALSE;
1674         *changePort = ( flags & ChangePortFlag )?TRUE:FALSE;
1675                       
1676         //ortp_debug("stun: Request is valid:\n");
1677         //ortp_debug("stun: \t flags= %i\n", flags );
1678         //ortp_debug("stun: \t changeIp= %i\n", *changeIp );
1679         //ortp_debug("stun: \t changePort=%i\n", *changePort );
1680         //ortp_debug("stun: \t from= %i\n", from->addr );
1681         //ortp_debug("stun: \t respond to= %i\n", respondTo.addr );
1682         //ortp_debug("stun: \t mapped= %i\n", mapped.addr );
1683                               
1684         /* form the outgoing message */
1685         resp->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_SUCCESS_RESP);
1686         resp->msgHdr.magic_cookie = ntohl(req.msgHdr.magic_cookie);
1687         for (i=0; i<12; i++ )
1688         {
1689            resp->msgHdr.tr_id.octet[i] = req.msgHdr.tr_id.octet[i];
1690         }
1691               
1692         if (1) /* do xorMapped address or not */
1693         {
1694            uint32_t cookie = 0x2112A442;
1695            resp->hasXorMappedAddress = TRUE;
1696            resp->xorMappedAddress.ipv4.port = mapped.port^(cookie>>16);
1697            resp->xorMappedAddress.ipv4.addr = mapped.addr^cookie;
1698         }
1699         
1700         resp->hasSourceAddress = TRUE;
1701         resp->sourceAddress.ipv4.port = (*changePort) ? altAddr->port : myAddr->port;
1702         resp->sourceAddress.ipv4.addr = (*changeIp)   ? altAddr->addr : myAddr->addr;
1703                       
1704         resp->hasChangedAddress = TRUE;
1705         resp->changedAddress.ipv4.port = altAddr->port;
1706         resp->changedAddress.ipv4.addr = altAddr->addr;
1707       
1708         if ( req.hasUsername && req.username.sizeValue > 0 ) 
1709         {
1710            /* copy username in */
1711            resp->hasUsername = TRUE;
1712            /* assert( req.username.sizeValue % 4 == 0 ); */
1713            /* assert( req.username.sizeValue < STUN_MAX_STRING ); */
1714            memcpy( resp->username.value, req.username.value, req.username.sizeValue );
1715            resp->username.sizeValue = req.username.sizeValue;
1716         }
1717               
1718         if (1) /* add ServerName */
1719         {
1720            const char serverName[] = "oRTP   " STUN_VERSION; /* must pad to mult of 4 */
1721            resp->hasSoftware = TRUE;
1722           
1723            /* assert( sizeof(serverName) < STUN_MAX_STRING ); */
1724            /* cerr << "sizeof serverName is "  << sizeof(serverName) ); */
1725            /* assert( sizeof(serverName)%4 == 0 ); */
1726            memcpy( resp->softwareName.value, serverName, sizeof(serverName));
1727            resp->softwareName.sizeValue = sizeof(serverName);
1728         }
1729         
1730#if 0
1731         if ( req.hasMessageIntegrity & req.hasUsername ) 
1732         {
1733            /* this creates the password that will be used in the HMAC when then */
1734            /* messages is sent */
1735            stunCreatePassword( &req.username, hmacPassword );
1736         }
1737#endif
1738
1739         if (req.hasUsername && (req.username.sizeValue > 64 ) )
1740         {
1741            uint32_t source;
1742            /* assert( sizeof(int) == sizeof(uint32_t) ); */
1743                                       
1744            sscanf(req.username.value, "%x", &source);
1745            resp->hasReflectedFrom = TRUE;
1746            resp->reflectedFrom.ipv4.port = 0;
1747            resp->reflectedFrom.ipv4.addr = source;
1748         }
1749                               
1750         destination->port = respondTo.port;
1751         destination->addr = respondTo.addr;
1752                       
1753         return TRUE;           
1754   }
1755   else
1756   {
1757         ortp_error("stun: Unknown or unsupported request ");
1758         return FALSE;
1759   }
1760       
1761   /* assert(0); */
1762   return FALSE;
1763}
1764
1765bool_t
1766stunInitServer(StunServerInfo *info, const StunAddress4 *myAddr, const StunAddress4 *altAddr, int startMediaPort)
1767{
1768   /* assert( myAddr.port != 0 ); */
1769   /* assert( altAddr.port!= 0 ); */
1770   /* assert( myAddr.addr  != 0 ); */
1771   /* assert( altAddr.addr != 0 ); */
1772       
1773   /* info->myAddr = myAddr; */
1774   info->myAddr.port = myAddr->port;
1775   info->myAddr.addr = myAddr->addr;
1776
1777   /* info->altAddr = altAddr; */
1778   info->altAddr.port = altAddr->port;
1779   info->altAddr.addr = altAddr->addr;
1780       
1781   info->myFd = INVALID_SOCKET;
1782   info->altPortFd = INVALID_SOCKET;
1783   info->altIpFd = INVALID_SOCKET;
1784   info->altIpPortFd = INVALID_SOCKET;
1785
1786   memset(info->relays, 0, sizeof(info->relays));
1787   if (startMediaPort > 0)
1788   {
1789      int i;
1790      info->relay = TRUE;
1791
1792      for (i=0; i<MAX_MEDIA_RELAYS; ++i)
1793      {
1794         StunMediaRelay* relay = &info->relays[i];
1795         relay->relayPort = startMediaPort+i;
1796         relay->fd = 0;
1797         relay->expireTime = 0;
1798      }
1799   }
1800   else
1801   {
1802      info->relay = FALSE;
1803   }
1804   
1805   if ((info->myFd = openPort(myAddr->port, myAddr->addr)) == INVALID_SOCKET)
1806   {
1807      ortp_error("stun: Can't open %i\n", myAddr->addr );
1808      stunStopServer(info);
1809
1810      return FALSE;
1811   }
1812
1813   if ((info->altPortFd = openPort(altAddr->port,myAddr->addr)) == INVALID_SOCKET)
1814   {
1815      ortp_error("stun: Can't open %i\n", myAddr->addr );
1816      stunStopServer(info);
1817      return FALSE;
1818   }
1819   
1820   
1821   info->altIpFd = INVALID_SOCKET;
1822   if (  altAddr->addr != 0 )
1823   {
1824      if ((info->altIpFd = openPort( myAddr->port, altAddr->addr)) == INVALID_SOCKET)
1825      {
1826         ortp_error("stun: Can't open %i\n", altAddr->addr );
1827         stunStopServer(info);
1828         return FALSE;
1829      }
1830   }
1831   
1832   info->altIpPortFd = INVALID_SOCKET;
1833   if (  altAddr->addr != 0 )
1834   {  if ((info->altIpPortFd = openPort(altAddr->port, altAddr->addr)) == INVALID_SOCKET)
1835      {
1836         ortp_error("stun: Can't open %i\n", altAddr->addr );
1837         stunStopServer(info);
1838         return FALSE;
1839      }
1840   }
1841   
1842   return TRUE;
1843}
1844
1845void
1846stunStopServer(StunServerInfo *info)
1847{
1848   if (info->myFd > 0) closesocket(info->myFd);
1849   if (info->altPortFd > 0) closesocket(info->altPortFd);
1850   if (info->altIpFd > 0) closesocket(info->altIpFd);
1851   if (info->altIpPortFd > 0) closesocket(info->altIpPortFd);
1852   
1853   if (info->relay)
1854   {
1855      int i;
1856      for (i=0; i<MAX_MEDIA_RELAYS; ++i)
1857      {
1858         StunMediaRelay* relay = &info->relays[i];
1859         if (relay->fd)
1860         {
1861            closesocket(relay->fd);
1862            relay->fd = 0;
1863         }
1864      }
1865   }
1866}
1867
1868int 
1869stunFindLocalInterfaces(uint32_t* addresses,int maxRet)
1870{
1871#if defined(WIN32) || defined(_WIN32_WCE) || defined(__sparc__)
1872   return 0;
1873#else
1874   struct ifconf ifc;
1875   int e;
1876
1877   int s = socket( AF_INET, SOCK_DGRAM, 0 );
1878   int len = 100 * sizeof(struct ifreq);
1879   
1880   char buf[ 100 * sizeof(struct ifreq) ];
1881   char *ptr;
1882   int tl;
1883   int count=0;
1884
1885   ifc.ifc_len = len;
1886   ifc.ifc_buf = buf;
1887       
1888   e = ioctl(s,SIOCGIFCONF,&ifc);
1889   ptr = buf;
1890   tl = ifc.ifc_len;
1891   
1892   while ( (tl > 0) && ( count < maxRet) )
1893   {
1894      struct ifreq* ifr = (struct ifreq *)ptr;
1895      struct ifreq ifr2;
1896      struct sockaddr a;
1897      struct sockaddr_in* addr;
1898   
1899      uint32_t ai;
1900      int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1901      tl -= si;
1902      ptr += si;
1903      /* char* name = ifr->ifr_ifrn.ifrn_name; */
1904      /* cerr << "name = " << name ); */
1905     
1906      ifr2 = *ifr;
1907     
1908      e = ioctl(s,SIOCGIFADDR,&ifr2);
1909      if ( e == -1 )
1910      {
1911         break;
1912      }
1913     
1914      /* cerr << "ioctl addr e = " << e ; */
1915     
1916      a = ifr2.ifr_addr;
1917      addr = (struct sockaddr_in*) &a;
1918     
1919      ai = ntohl( addr->sin_addr.s_addr );
1920      if ((int)((ai>>24)&0xFF) != 127)
1921      {
1922         addresses[count++] = ai;
1923      }
1924               
1925   }
1926   
1927   closesocket(s);
1928   
1929   return count;
1930#endif
1931}
1932
1933
1934void
1935stunBuildReqSimple( StunMessage* msg,
1936                    const StunAtrString *username,
1937                    bool_t changePort, bool_t changeIp, unsigned int id )
1938{
1939   int i;
1940   /* assert( msg ); */
1941   memset( msg , 0 , sizeof(*msg) );
1942       
1943   msg->msgHdr.msgType = (STUN_METHOD_BINDING|STUN_REQUEST);
1944       
1945   msg->msgHdr.magic_cookie = 0x2112A442;
1946   for ( i=0; i<12; i=i+4 )
1947   {
1948      /* assert(i+3<16); */
1949      int r = stunRand();
1950      msg->msgHdr.tr_id.octet[i+0]= r>>0;
1951      msg->msgHdr.tr_id.octet[i+1]= r>>8;
1952      msg->msgHdr.tr_id.octet[i+2]= r>>16;
1953      msg->msgHdr.tr_id.octet[i+3]= r>>24;
1954   }
1955       
1956   if ( id != 0 )
1957   {
1958      msg->msgHdr.tr_id.octet[0] = id; 
1959   }
1960       
1961   if (changePort==TRUE || changeIp==TRUE)
1962   {
1963     msg->hasChangeRequest = TRUE;
1964     msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 
1965        (changePort?ChangePortFlag:0);
1966   }
1967
1968   if ( username!=NULL && username->sizeValue > 0 )
1969   {
1970      msg->hasUsername = TRUE;
1971      /* msg->username = username; */
1972      memcpy(&msg->username, username, sizeof(StunAtrString));
1973   }
1974}
1975
1976
1977static void 
1978stunSendTest( Socket myFd, StunAddress4 *dest, 
1979              const StunAtrString *username, const StunAtrString *password, 
1980              int testNum )
1981{ 
1982   /* assert( dest.addr != 0 ); */
1983   /* assert( dest.port != 0 ); */
1984       
1985   bool_t changePort=FALSE;
1986   bool_t changeIP=FALSE;
1987   bool_t discard=FALSE;
1988
1989   StunMessage req;
1990   char buf[STUN_MAX_MESSAGE_SIZE];
1991   int len = STUN_MAX_MESSAGE_SIZE;
1992   
1993   switch (testNum)
1994   {
1995      case 1:
1996      case 10:
1997      case 11:
1998         break;
1999      case 2:
2000         /* changePort=TRUE; */
2001         changeIP=TRUE;
2002         break;
2003      case 3:
2004         changePort=TRUE;
2005         break;
2006      case 4:
2007         changeIP=TRUE;
2008         break;
2009      case 5:
2010         discard=TRUE;
2011         break;
2012      default:
2013         ortp_error("stun: Test %i is unkown\n", testNum);
2014         return ; /* error */
2015   }
2016   
2017   memset(&req, 0, sizeof(StunMessage));
2018       
2019   stunBuildReqSimple( &req, username, 
2020                       changePort , changeIP , 
2021                       testNum );
2022       
2023   len = stunEncodeMessage( &req, buf, len, password );
2024       
2025   //ortp_debug("stun: About to send msg of len %i to %s\n", len, ipaddr(dest) );
2026       
2027   sendMessage( myFd, buf, len, dest->addr, dest->port );
2028       
2029   /* add some delay so the packets don't get sent too quickly */
2030#if defined(_WIN32_WCE)
2031   Sleep (10);
2032#elif defined(WIN32)/* !cj! TODO - should fix this up in windows */
2033   {
2034       clock_t now = clock();
2035       /* assert( CLOCKS_PER_SEC == 1000 ); */
2036       while ( clock() <= now+10 ) { };
2037   }
2038#else
2039                 usleep(10*1000);
2040#endif
2041
2042}
2043
2044
2045#if 0
2046void
2047stunGetUserNameAndPassword(  const StunAddress4 *dest,
2048                             StunAtrString* username,
2049                             StunAtrString* password)
2050{
2051   /* !cj! This is totally bogus - need to make TLS connection to dest and get a */
2052   /* username and password to use */
2053   stunCreateUserName(dest, username);
2054   stunCreatePassword(username, password);
2055}
2056#endif
2057
2058int 
2059stunTest( StunAddress4 *dest, int testNum, StunAddress4* sAddr , StunAddress4 *sMappedAddr, StunAddress4* sChangedAddr)
2060{
2061   /* assert( dest.addr != 0 ); */
2062   /* assert( dest.port != 0 ); */
2063       
2064   int port = randomPort();
2065   uint32_t interfaceIp=0;
2066   Socket myFd;
2067   StunAtrString username;
2068   StunAtrString password;
2069   char msg[STUN_MAX_MESSAGE_SIZE];
2070   int msgLen = STUN_MAX_MESSAGE_SIZE;
2071   StunAddress4 from;
2072   StunMessage resp;
2073   bool_t ok;
2074
2075   if (sAddr)
2076   {
2077      interfaceIp = sAddr->addr;
2078      if ( sAddr->port != 0 )
2079      {
2080        port = sAddr->port;
2081      }
2082   }
2083   myFd = openPort(port,interfaceIp);
2084   if ( myFd == INVALID_SOCKET)
2085       return -1;
2086   
2087   username.sizeValue = 0;
2088   password.sizeValue = 0;
2089       
2090#if 0
2091   stunGetUserNameAndPassword( dest, &username, &password );
2092#endif
2093       
2094   stunSendTest( myFd, dest, &username, &password, testNum );
2095   
2096   ok = getMessage( myFd,
2097               msg,
2098               &msgLen,
2099               &from.addr,
2100               &from.port );
2101   closesocket(myFd);
2102   if (!ok)
2103       return -1;
2104
2105   memset(&resp, 0, sizeof(StunMessage));
2106       
2107   //ortp_debug("stun: Got a response");
2108   ok = stunParseMessage( msg,msgLen, &resp );
2109       
2110   //ortp_debug("stun: \t ok=%i\n", ok );
2111   //ortp_debug("stun: \t SA_MAPPEDADDRESS=%i\n", resp.mappedAddress.ipv4.addr );
2112   //ortp_debug("stun: \t SA_CHANGEDADDRESS=%i\n", resp.changedAddress.ipv4.addr );
2113       
2114   if (sAddr)
2115   {
2116       sAddr->port = port;
2117   }
2118
2119   if (sMappedAddr)
2120   {
2121      sMappedAddr->port = resp.mappedAddress.ipv4.port;
2122      sMappedAddr->addr = resp.mappedAddress.ipv4.addr;
2123   }
2124
2125   if (sChangedAddr)
2126   {
2127      sChangedAddr->port = resp.changedAddress.ipv4.port;
2128      sChangedAddr->addr = resp.changedAddress.ipv4.addr;
2129   }
2130
2131   if (ok)
2132       return 0;
2133   else
2134       return -1;
2135}
2136
2137
2138
2139
2140NatType
2141stunNatType( StunAddress4 *dest, 
2142             bool_t* preservePort, /* if set, is return for if NAT preservers ports or not */
2143             bool_t* hairpin,  /* if set, is the return for if NAT will hairpin packets */
2144             int port, /* port to use for the test, 0 to choose random port */
2145             StunAddress4* sAddr /* NIC to use */
2146   )
2147{ 
2148   /* assert( dest.addr != 0 ); */
2149   /* assert( dest.port != 0 ); */
2150   uint32_t interfaceIp=0;
2151   Socket myFd1;
2152   Socket myFd2;
2153
2154   bool_t respTestI=FALSE;
2155   bool_t isNat=TRUE;
2156   StunAddress4 testIchangedAddr;
2157   StunAddress4 testImappedAddr;
2158   bool_t respTestI2=FALSE; 
2159   bool_t mappedIpSame = TRUE;
2160   StunAddress4 testI2mappedAddr;
2161   /* StunAddress4 testI2dest=dest; */
2162   StunAddress4 testI2dest;
2163   bool_t respTestII=FALSE;
2164   bool_t respTestIII=FALSE;
2165   bool_t respTestHairpin=FALSE;
2166   StunAtrString username;
2167   StunAtrString password;
2168   int count=0;
2169   uint64_t second_started;
2170   uint64_t second_elapsed;
2171   Socket s;
2172
2173   if ( hairpin ) 
2174   {
2175      *hairpin = FALSE;
2176   }
2177       
2178   if ( port == 0 )
2179   {
2180      port = randomPort();
2181   }
2182
2183   if (sAddr)
2184   {
2185      interfaceIp = sAddr->addr;
2186   }
2187   myFd1 = openPort(port,interfaceIp);
2188   myFd2 = openPort(port+1,interfaceIp);
2189
2190   if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )
2191   {
2192      ortp_error("stun: Some problem opening port/interface to send on\n");
2193      return StunTypeFailure; 
2194   }
2195
2196   /* assert( myFd1 != INVALID_SOCKET ); */
2197   /* assert( myFd2 != INVALID_SOCKET ); */
2198   
2199   memcpy(&testI2dest, dest, sizeof(StunAddress4));
2200
2201   memset(&testImappedAddr,0,sizeof(testImappedAddr));
2202   
2203   username.sizeValue = 0;
2204   password.sizeValue = 0;
2205       
2206#if 0 
2207   stunGetUserNameAndPassword( dest, username, password );
2208#endif
2209       
2210   /* stunSendTest( myFd1, dest, username, password, 1 ); */
2211
2212   
2213   second_started = stunGetSystemTimeSecs();
2214   second_elapsed = 1;
2215
2216   while ( count < 3 && second_elapsed < 5)
2217   {
2218      struct timeval tv;
2219      fd_set fdSet; 
2220      int err;
2221      int e;
2222
2223#if defined(WIN32) || defined(_WIN32_WCE)
2224      unsigned int fdSetSize;
2225#else
2226      int fdSetSize;
2227#endif
2228
2229      second_elapsed = stunGetSystemTimeSecs() - second_started ;
2230
2231      FD_ZERO(&fdSet); fdSetSize=0;
2232      FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;
2233      FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;
2234      tv.tv_sec=0;
2235      tv.tv_usec=500*1000; /* 150 ms */
2236      if ( count == 0 ) tv.tv_usec=0;
2237               
2238      err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
2239      e = getErrno();
2240      if ( err == SOCKET_ERROR )
2241      {
2242         /* error occured */
2243#if !defined(_WIN32_WCE)
2244         ortp_error("stun: Error %i %s in select\n", e, strerror(e));
2245#else
2246         ortp_error("stun: Error %i in select\n", e);
2247#endif
2248                 closesocket(myFd1); /* AMD */
2249         closesocket(myFd2); /* AMD */
2250         return StunTypeFailure;
2251     }
2252      else if ( err == 0 )
2253      {
2254         /* timeout occured */
2255         count++;
2256         if ( !respTestI ) 
2257         {
2258            stunSendTest( myFd1, dest, &username, &password, 1 );
2259         }         
2260                       
2261         if ( (!respTestI2) && respTestI ) 
2262         {
2263            /* check the address to send to if valid */
2264            if (  ( testI2dest.addr != 0 ) &&
2265                  ( testI2dest.port != 0 ) )
2266            {
2267               stunSendTest( myFd1, &testI2dest, &username, &password, 10 );
2268            }
2269         }
2270                       
2271         if ( !respTestII )
2272         {
2273            stunSendTest( myFd2, dest, &username, &password, 2 );
2274         }
2275                       
2276         if ( !respTestIII )
2277         {
2278            stunSendTest( myFd2, dest, &username, &password, 3 );
2279         }
2280                       
2281         if ( respTestI && (!respTestHairpin) )
2282         {
2283            if (  ( testImappedAddr.addr != 0 ) &&
2284                  ( testImappedAddr.port != 0 ) )
2285            {
2286               stunSendTest( myFd1, &testImappedAddr, &username, &password, 11 );
2287            }
2288         }
2289
2290      }
2291      else
2292      {
2293         int i;
2294         /* data is avialbe on some fd */
2295                       
2296         for ( i=0; i<2; i++)
2297         {
2298            Socket myFd;
2299            if ( i==0 ) 
2300            {
2301               myFd=myFd1;
2302            }
2303            else
2304            {
2305               myFd=myFd2;
2306            }
2307                               
2308            if ( myFd!=INVALID_SOCKET ) 
2309            {                                   
2310               if ( FD_ISSET(myFd,&fdSet) )
2311               {
2312                  char msg[STUN_MAX_MESSAGE_SIZE];
2313                  int msgLen = sizeof(msg);
2314                                                               
2315                  StunAddress4 from;
2316                  StunMessage resp;
2317
2318                  getMessage( myFd,
2319                              msg,
2320                              &msgLen,
2321                              &from.addr,
2322                              &from.port );
2323                 
2324                  memset(&resp, 0, sizeof(StunMessage));
2325                                               
2326                  stunParseMessage( msg,msgLen, &resp );
2327                                               
2328                  //ortp_debug("stun: Received message of type %i id=%i\n",
2329                          //resp.msgHdr.msgType,
2330                          //(int)(resp.msgHdr.tr_id.octet[0]) );
2331                                               
2332                  switch( resp.msgHdr.tr_id.octet[0] )
2333                  {
2334                     case 1:
2335                     {
2336                        if ( !respTestI )
2337                        {
2338                                                                       
2339                           testIchangedAddr.addr = resp.changedAddress.ipv4.addr;
2340                           testIchangedAddr.port = resp.changedAddress.ipv4.port;
2341                           testImappedAddr.addr = resp.mappedAddress.ipv4.addr;
2342                           testImappedAddr.port = resp.mappedAddress.ipv4.port;
2343                                                                       
2344                           if ( preservePort )
2345                           {
2346                              *preservePort = ( testImappedAddr.port == port );
2347                           }                                                           
2348                                                                       
2349                           testI2dest.addr = resp.changedAddress.ipv4.addr;
2350                                                                       
2351                           if (sAddr)
2352                           {
2353                              sAddr->port = testImappedAddr.port;
2354                              sAddr->addr = testImappedAddr.addr;
2355                           }
2356                                                                       
2357                           count = 0;
2358                        }               
2359                        respTestI=TRUE;
2360                     }
2361                     break;
2362                     case 2:
2363                     { 
2364                        respTestII=TRUE;
2365                     }
2366                     break;
2367                     case 3:
2368                     {
2369                        respTestIII=TRUE;
2370                     }
2371                     break;
2372                     case 10:
2373                     {
2374                        if ( !respTestI2 )
2375                        {
2376                           testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;
2377                           testI2mappedAddr.port = resp.mappedAddress.ipv4.port;
2378                                                               
2379                           mappedIpSame = FALSE;
2380                           if ( (testI2mappedAddr.addr  == testImappedAddr.addr ) &&
2381                                (testI2mappedAddr.port == testImappedAddr.port ))
2382                           { 
2383                              mappedIpSame = TRUE;
2384                           }
2385                                                               
2386                                                       
2387                        }
2388                        respTestI2=TRUE;
2389                     }
2390                     break;
2391                     case 11:
2392                     {
2393                                                       
2394                        if ( hairpin ) 
2395                        {
2396                           *hairpin = TRUE;
2397                        }
2398                        respTestHairpin = TRUE;
2399                     }
2400                     break;
2401                  }
2402               }
2403            }
2404         }
2405      }
2406   }
2407       
2408   closesocket(myFd1); /* AMD */
2409   closesocket(myFd2); /* AMD */
2410
2411   /* see if we can bind to this address */
2412   /* cerr << "try binding to " << testImappedAddr ); */
2413   s = openPort( 0/*use ephemeral*/, testImappedAddr.addr );
2414   if ( s != INVALID_SOCKET )
2415   {
2416      isNat = FALSE;
2417      /* cerr << "binding worked"); */
2418   }
2419   else
2420   {
2421      isNat = TRUE;
2422      /* cerr << "binding failed"); */
2423   }
2424
2425   closesocket(s); /* AMD */
2426       
2427   //ortp_debug("stun: test I = %i\n", respTestI );
2428   //ortp_debug("stun: test II = %i\n", respTestII );
2429   //ortp_debug("stun: test III = %i\n", respTestIII );
2430   //ortp_debug("stun: test I(2) = %i\n", respTestI2 );
2431   ortp_debug("stun: is nat  = %i\n", isNat);
2432   ortp_debug("stun: mapped IP same = %i\n", mappedIpSame );
2433       
2434   /* implement logic flow chart from draft RFC */
2435   if ( respTestI )
2436   {
2437      if ( isNat )
2438      {
2439         if (respTestII)
2440         {
2441            return StunTypeConeNat;
2442         }
2443         else
2444         {
2445            if ( mappedIpSame )
2446            {
2447               if ( respTestIII )
2448               {
2449                  return StunTypeRestrictedNat;
2450               }
2451               else
2452               {
2453                  return StunTypePortRestrictedNat;
2454               }
2455            }
2456            else
2457            {
2458               return StunTypeSymNat;
2459            }
2460         }
2461      }
2462      else
2463      {
2464         if (respTestII)
2465         {
2466            return StunTypeOpen;
2467         }
2468         else
2469         {
2470            return StunTypeSymFirewall;
2471         }
2472      }
2473   }
2474   else
2475   {
2476      return StunTypeBlocked;
2477   }
2478       
2479   return StunTypeUnknown;
2480}
2481
2482int
2483stunOpenSocket( StunAddress4 *dest, StunAddress4* mapAddr, 
2484                int port, StunAddress4* srcAddr )
2485{
2486   /* assert( dest.addr != 0 ); */
2487   /* assert( dest.port != 0 ); */
2488   /* assert( mapAddr );*/
2489   unsigned int interfaceIp = 0;
2490   Socket myFd;
2491   char msg[STUN_MAX_MESSAGE_SIZE];
2492   int msgLen = sizeof(msg);
2493       
2494   StunAtrString username;
2495   StunAtrString password;
2496
2497   StunAddress4 from;
2498   StunMessage resp;
2499   bool_t ok;
2500   StunAddress4 mappedAddr;
2501
2502   if ( port == 0 )
2503   {
2504      port = randomPort();
2505   }
2506
2507   if ( srcAddr )
2508   {
2509      interfaceIp = srcAddr->addr;
2510   }
2511   
2512   myFd = openPort(port,interfaceIp);
2513   if (myFd == INVALID_SOCKET)
2514   {
2515      return myFd;
2516   }
2517   
2518   username.sizeValue = 0;
2519   password.sizeValue = 0;
2520       
2521#if 0
2522   stunGetUserNameAndPassword( dest, username, password );
2523#endif
2524       
2525   stunSendTest(myFd, dest, &username, &password, 1 );
2526       
2527   getMessage( myFd, msg, &msgLen, &from.addr, &from.port );
2528
2529   memset(&resp, 0, sizeof(StunMessage));
2530       
2531   ok = stunParseMessage( msg, msgLen, &resp );
2532   if (!ok)
2533   {
2534       closesocket(myFd);
2535       return -1;
2536   }
2537
2538   if (resp.hasXorMappedAddress==TRUE)
2539   {
2540      uint32_t cookie = 0x2112A442;
2541      uint16_t cookie16 = 0x2112A442 >> 16;
2542      mappedAddr.port = resp.xorMappedAddress.ipv4.port^cookie16;
2543      mappedAddr.addr = resp.xorMappedAddress.ipv4.addr^cookie;
2544   }
2545   else
2546     mappedAddr = resp.mappedAddress.ipv4;
2547       
2548   /*
2549     ortp_message("stun: --- stunOpenSocket --- ");
2550     ortp_message("stun: \treq  id=" << req.id );
2551     ortp_message("stun: \tresp id=" << id );
2552     ortp_message("stun: \tmappedAddr=" << mappedAddr );
2553   */
2554
2555   *mapAddr = mappedAddr;
2556       
2557   return myFd;
2558}
2559
2560
2561bool_t
2562stunOpenSocketPair(StunAddress4 *dest,
2563                   StunAddress4* mapAddr_rtp, 
2564                   StunAddress4* mapAddr_rtcp, 
2565                   int* fd1, int* fd2, 
2566                   int port, StunAddress4* srcAddr )
2567{
2568   /* assert( dest.addr!= 0 ); */
2569   /* assert( dest.port != 0 ); */
2570   /* assert( mapAddr ); */
2571   
2572   const int NUM=2;
2573   char msg[STUN_MAX_MESSAGE_SIZE];
2574   int msgLen =sizeof(msg);
2575       
2576   StunAddress4 from;
2577   int fd[2/*NUM*/];
2578   int i;
2579       
2580   unsigned int interfaceIp = 0;
2581       
2582   StunAtrString username;
2583   StunAtrString password;
2584       
2585   StunAddress4 mappedAddr[2/*NUM*/];
2586
2587   if ( port == 0 )
2588   {
2589      port = randomPort();
2590   }
2591       
2592   *fd1=-1;
2593   *fd2=-1;
2594       
2595   if ( srcAddr )
2596   {
2597      interfaceIp = srcAddr->addr;
2598   }
2599
2600   for( i=0; i<NUM; i++)
2601   {
2602      fd[i] = openPort( (port == 0) ? 0 : (port + i), interfaceIp);
2603      if (fd[i] < 0) 
2604      {
2605         while (i > 0)
2606         {
2607            closesocket(fd[--i]);
2608         }
2609         return FALSE;
2610      }
2611   }
2612       
2613   username.sizeValue = 0;
2614   password.sizeValue = 0;
2615       
2616#if 0
2617   stunGetUserNameAndPassword( dest, username, password );
2618#endif
2619       
2620   for( i=0; i<NUM; i++)
2621   {
2622      stunSendTest(fd[i], dest, &username, &password, 1/*testNum*/ );
2623   }
2624   
2625   for( i=0; i<NUM; i++)
2626   {
2627      StunMessage resp;
2628      bool_t ok;
2629      msgLen = sizeof(msg)/sizeof(*msg);
2630      getMessage( fd[i],
2631                  msg,
2632                  &msgLen,
2633                  &from.addr,
2634                  &from.port);
2635     
2636      memset(&resp, 0, sizeof(StunMessage));
2637               
2638      ok = stunParseMessage( msg, msgLen, &resp );
2639      if (!ok) 
2640      { 
2641          for( i=0; i<NUM; i++)
2642          {
2643              closesocket(fd[i]);
2644          }
2645         return FALSE;
2646      }
2647         
2648      if (resp.hasXorMappedAddress==TRUE)
2649      {
2650        uint32_t cookie = 0x2112A442;
2651        uint16_t cookie16 = 0x2112A442 >> 16;
2652        mappedAddr[i].port = resp.xorMappedAddress.ipv4.port^cookie16;
2653        mappedAddr[i].addr = resp.xorMappedAddress.ipv4.addr^cookie;
2654      }
2655      else
2656        mappedAddr[i] = resp.mappedAddress.ipv4;
2657   }
2658       
2659   //ortp_debug("stun: --- stunOpenSocketPair --- \n");
2660   for( i=0; i<NUM; i++)
2661   {
2662      //ortp_debug("stun: \t mappedAddr=%s\n", ipaddr(&mappedAddr[i]) );
2663   }
2664       
2665    *mapAddr_rtp = mappedAddr[0];
2666    *mapAddr_rtcp = mappedAddr[1];
2667    *fd1 = fd[0];
2668    *fd2 = fd[1];
2669
2670   for( i=0; i<NUM; i++)
2671   {
2672      closesocket( fd[i] );
2673   }
2674       
2675   return TRUE;
2676}
2677
2678static void 
2679turnSendAllocate( Socket myFd, StunAddress4 *dest, 
2680              const StunAtrString *username, const StunAtrString *password,
2681              StunMessage *resp)
2682{ 
2683  StunMessage req;
2684  char buf[STUN_MAX_MESSAGE_SIZE];
2685  int len = STUN_MAX_MESSAGE_SIZE;
2686  const char serverName[] = "oRTP   " STUN_VERSION; /* must pad to mult of 4 */
2687
2688  memset(&req, 0, sizeof(StunMessage));
2689
2690  stunBuildReqSimple( &req, username, 
2691                     FALSE , FALSE , 
2692                     0 );
2693  req.msgHdr.msgType = (TURN_MEDHOD_ALLOCATE|STUN_REQUEST);
2694
2695  req.hasSoftware = TRUE;
2696  memcpy( req.softwareName.value, serverName, sizeof(serverName));
2697  req.softwareName.sizeValue = sizeof(serverName);
2698
2699  req.hasRequestedTransport = TRUE;
2700  memset(&req.requestedTransport, 0, sizeof(req.requestedTransport));
2701  req.requestedTransport.proto = IPPROTO_UDP;
2702
2703  req.hasDontFragment = TRUE;
2704
2705  if (resp!=NULL
2706    && username!=NULL && username->sizeValue>0
2707    && password!=NULL && password->sizeValue>0
2708    && resp->hasRealm==TRUE
2709    && resp->hasNonce==TRUE)
2710  {
2711    req.hasUsername = TRUE;
2712    memcpy( req.username.value, username->value, username->sizeValue );
2713    req.username.sizeValue = username->sizeValue;
2714
2715    req.hasNonce = TRUE;
2716    memcpy( &req.nonceName, &resp->nonceName, sizeof(resp->nonceName));
2717
2718    req.hasRealm = TRUE;
2719    memcpy( &req.realmName, &resp->realmName, sizeof(resp->realmName));
2720
2721    req.hasMessageIntegrity = TRUE;
2722  }
2723
2724  len = stunEncodeMessage( &req, buf, len, password );
2725
2726  ortp_debug("stun: About to send msg of len %i to %s\n", len, ipaddr(dest) );
2727
2728  sendMessage( myFd, buf, len, dest->addr, dest->port);
2729
2730  /* add some delay so the packets don't get sent too quickly */
2731#if defined(_WIN32_WCE)
2732  Sleep (10);
2733#elif defined(WIN32)/* !cj! TODO - should fix this up in windows */
2734  {
2735    clock_t now = clock();
2736    /* assert( CLOCKS_PER_SEC == 1000 ); */
2737    while ( clock() <= now+10 ) { };
2738  }
2739#else
2740  usleep(10*1000);
2741#endif
2742}
2743
2744bool_t
2745turnAllocateSocketPair(StunAddress4 *dest,
2746                   StunAddress4* mapAddr_rtp, 
2747                   StunAddress4* mapAddr_rtcp, 
2748                   int* fd1, int* fd2, 
2749                   int port, StunAddress4* srcAddr)
2750{
2751   const int NUM=2;
2752   char msg[STUN_MAX_MESSAGE_SIZE];
2753   int msgLen =sizeof(msg);
2754       
2755   StunAddress4 from;
2756   int fd[2/*NUM*/];
2757   int i;
2758       
2759   unsigned int interfaceIp = 0;
2760       
2761   StunAtrString username;
2762   StunAtrString password;
2763       
2764   StunAddress4 mappedAddr[2/*NUM*/];
2765
2766   if ( port == 0 )
2767   {
2768      port = randomPort();
2769   }
2770       
2771   *fd1=-1;
2772   *fd2=-1;
2773       
2774   if ( srcAddr )
2775   {
2776      interfaceIp = srcAddr->addr;
2777   }
2778
2779   for( i=0; i<NUM; i++)
2780   {
2781      fd[i] = openPort( (port == 0) ? 0 : (port + i), 
2782                        interfaceIp);
2783      if (fd[i] < 0) 
2784      {
2785         while (i > 0)
2786         {
2787            closesocket(fd[--i]);
2788         }
2789         return FALSE;
2790      }
2791   }
2792       
2793   snprintf(username.value, sizeof(username.value), "antisip");
2794   username.sizeValue = strlen(username.value);
2795   snprintf(password.value, sizeof(password.value), "exosip");
2796   password.sizeValue = strlen(password.value);
2797       
2798   for( i=0; i<NUM; i++)
2799   {
2800      turnSendAllocate(fd[i], dest, NULL, NULL, NULL );
2801   }
2802   
2803   for( i=0; i<NUM; i++)
2804   {
2805      StunMessage resp;
2806      bool_t ok;
2807      msgLen = sizeof(msg)/sizeof(*msg);
2808      getMessage( fd[i],
2809                  msg,
2810                  &msgLen,
2811                  &from.addr,
2812                  &from.port);
2813     
2814      memset(&resp, 0, sizeof(StunMessage));
2815               
2816      ok = stunParseMessage( msg, msgLen, &resp );
2817      if (!ok) 
2818      { 
2819          for( i=0; i<NUM; i++)
2820          {
2821              closesocket(fd[i]);
2822          }
2823         return FALSE;
2824      }
2825
2826      if (STUN_IS_ERR_RESP(resp.msgHdr.msgType))
2827      {
2828        /* check if we need to authenticate */
2829        if (resp.hasErrorCode==TRUE
2830          && resp.errorCode.errorClass==4 && resp.errorCode.number==1
2831          && resp.hasNonce == TRUE
2832          && resp.hasRealm == TRUE)
2833        {
2834          turnSendAllocate(fd[i], dest, &username, &password, &resp);
2835          i--;
2836        }
2837      }
2838      else if (STUN_IS_SUCCESS_RESP(resp.msgHdr.msgType))
2839      {
2840        if (resp.hasXorRelayedAddress==TRUE)
2841        {
2842          uint32_t cookie = 0x2112A442;
2843          uint16_t cookie16 = 0x2112A442 >> 16;
2844          mappedAddr[i].port = resp.xorRelayedAddress.ipv4.port^cookie16;
2845          mappedAddr[i].addr = resp.xorRelayedAddress.ipv4.addr^cookie;
2846        }
2847        else
2848        {
2849          for( i=0; i<NUM; i++)
2850          {
2851            closesocket(fd[i]);
2852          }
2853          return FALSE;
2854        }
2855      }
2856   }
2857       
2858  for( i=0; i<NUM; i++)
2859  {
2860     ortp_message("stun: stunOpenSocketPair mappedAddr=%s\n", ipaddr(&mappedAddr[i]) );
2861  }
2862       
2863  *mapAddr_rtp = mappedAddr[0];
2864  *mapAddr_rtcp = mappedAddr[1];
2865  *fd1 = fd[0];
2866  *fd2 = fd[1];
2867
2868  for( i=0; i<NUM; i++)
2869  {
2870    closesocket( fd[i] );
2871  }
2872       
2873  return TRUE;
2874}
2875
2876/* Local Variables:
2877   mode:c
2878   c-file-style:"ellemtel"
2879   c-file-offsets:((case-label . +))
2880   indent-tabs-mode:nil
2881   End:
2882*/
2883
Note: See TracBrowser for help on using the repository browser.