summaryrefslogtreecommitdiffstats
path: root/media/mtransport/third_party
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /media/mtransport/third_party
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'media/mtransport/third_party')
-rw-r--r--media/mtransport/third_party/import.py40
-rw-r--r--media/mtransport/third_party/moz.build76
-rw-r--r--media/mtransport/third_party/nICEr/IMPORT_FILES71
-rw-r--r--media/mtransport/third_party/nICEr/README74
-rw-r--r--media/mtransport/third_party/nICEr/README_MOZILLA11
-rw-r--r--media/mtransport/third_party/nICEr/nicer.gyp254
-rw-r--r--media/mtransport/third_party/nICEr/src/crypto/nr_crypto.c71
-rw-r--r--media/mtransport/third_party/nICEr/src/crypto/nr_crypto.h52
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_candidate.c979
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_candidate.h121
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c684
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h95
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_codeword.h41
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_component.c1688
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_component.h104
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_ctx.c1057
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_ctx.h203
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_handler.h84
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c933
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h108
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_parser.c575
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c825
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h101
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_reg.h79
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_socket.c380
-rw-r--r--media/mtransport/third_party/nICEr/src/ice/ice_socket.h97
-rw-r--r--media/mtransport/third_party/nICEr/src/net/local_addr.c61
-rw-r--r--media/mtransport/third_party/nICEr/src/net/local_addr.h59
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.c88
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.h66
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c686
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h70
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_resolver.c85
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_resolver.h96
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket.c191
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket.h121
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket_local.h41
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c620
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.h52
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.c82
-rw-r--r--media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.h63
-rw-r--r--media/mtransport/third_party/nICEr/src/net/transport_addr.c476
-rw-r--r--media/mtransport/third_party/nICEr/src/net/transport_addr.h103
-rw-r--r--media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c233
-rw-r--r--media/mtransport/third_party/nICEr/src/net/transport_addr_reg.h46
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/addrs.c444
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/addrs.h43
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c242
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h57
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c610
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.h64
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.c198
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.h48
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun.h216
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_build.c614
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_build.h147
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.c824
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.h199
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_codec.c1522
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_codec.h78
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_hint.c249
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_hint.h44
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_msg.c360
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_msg.h206
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_proc.c568
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_proc.h53
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_reg.h58
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c472
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.h82
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_util.c322
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/stun_util.h56
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c1056
-rw-r--r--media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.h137
-rw-r--r--media/mtransport/third_party/nICEr/src/util/cb_args.c61
-rw-r--r--media/mtransport/third_party/nICEr/src/util/cb_args.h41
-rw-r--r--media/mtransport/third_party/nICEr/src/util/ice_util.c76
-rw-r--r--media/mtransport/third_party/nICEr/src/util/ice_util.h41
-rw-r--r--media/mtransport/third_party/nICEr/src/util/mbslen.c139
-rw-r--r--media/mtransport/third_party/nICEr/src/util/mbslen.h42
-rw-r--r--media/mtransport/third_party/nICEr/upstream.diff2449
-rw-r--r--media/mtransport/third_party/nrappkit/COPYRIGHT159
-rw-r--r--media/mtransport/third_party/nrappkit/IMPORT_FILES87
-rw-r--r--media/mtransport/third_party/nrappkit/README133
-rw-r--r--media/mtransport/third_party/nrappkit/README_MOZILLA22
-rw-r--r--media/mtransport/third_party/nrappkit/VERSION1
-rw-r--r--media/mtransport/third_party/nrappkit/nrappkit.gyp234
-rw-r--r--media/mtransport/third_party/nrappkit/src/event/async_timer.h54
-rw-r--r--media/mtransport/third_party/nrappkit/src/event/async_wait.h83
-rw-r--r--media/mtransport/third_party/nrappkit/src/event/async_wait_int.h62
-rw-r--r--media/mtransport/third_party/nrappkit/src/log/r_log.c694
-rw-r--r--media/mtransport/third_party/nrappkit/src/log/r_log.h85
-rw-r--r--media/mtransport/third_party/nrappkit/src/plugin/nr_plugin.h57
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/android/include/android_funcs.h62
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/android/include/csi_platform.h55
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/android/include/sys/ttycom.h38
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/android/port-impl.mk31
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h57
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/generic/include/sys/queue.h562
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h55
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/linux/include/linux_funcs.h62
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/linux/include/sys/ttycom.h38
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/linux/port-impl.mk31
-rw-r--r--media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h107
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/c2ru.c320
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/c2ru.h96
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registry.c604
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registry.h154
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registry_int.h97
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registry_local.c1168
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registry_vtbl.h96
-rw-r--r--media/mtransport/third_party/nrappkit/src/registry/registrycb.c440
-rw-r--r--media/mtransport/third_party/nrappkit/src/share/nr_api.h51
-rw-r--r--media/mtransport/third_party/nrappkit/src/share/nr_common.h108
-rw-r--r--media/mtransport/third_party/nrappkit/src/share/nr_reg_keys.h167
-rw-r--r--media/mtransport/third_party/nrappkit/src/stats/nrstats.h118
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/byteorder.c76
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/byteorder.h47
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/hex.c110
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/hex.h47
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/assoc.h90
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/debug.c131
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/debug.h94
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.c541
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.h126
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_common.h100
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c177
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.h14
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_data.c249
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_data.h108
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_defaults.h91
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.c139
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.h127
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_includes.h98
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_list.c276
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_list.h106
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h137
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.c201
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.h101
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_replace.c110
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_thread.h68
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_time.c238
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h109
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/libekr/r_types.h213
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/p_buf.c217
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/p_buf.h72
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/util.c792
-rw-r--r--media/mtransport/third_party/nrappkit/src/util/util.h74
-rw-r--r--media/mtransport/third_party/nrappkit/upstream.diff391
148 files changed, 35518 insertions, 0 deletions
diff --git a/media/mtransport/third_party/import.py b/media/mtransport/third_party/import.py
new file mode 100644
index 000000000..6defdf26b
--- /dev/null
+++ b/media/mtransport/third_party/import.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# Execute as: /import.py <source-distribution> <target-dir>
+# <target-dir> must have 'IMPORT_FILES' in it
+
+import sys
+import re
+import os
+import shutil
+
+def die(msg):
+ sys.stderr.write('ERROR:' + msg + '\n')
+ sys.exit(1)
+
+DISTRO = sys.argv[1]
+IMPORT_DIR = sys.argv[2]
+FILES = []
+
+f = open("%s/IMPORT_FILES" % IMPORT_DIR)
+for l in f:
+ l = l.strip()
+ l = l.strip("'")
+ if l.startswith("#"):
+ continue
+ if not l:
+ continue
+ FILES.append(l)
+
+for f in FILES:
+ print f
+ SOURCE_PATH = "%s/%s"%(DISTRO,f)
+ DEST_PATH = "%s/%s"%(IMPORT_DIR,f)
+ if not os.path.exists(SOURCE_PATH):
+ die("%s does not exist"%SOURCE_PATH)
+ if not os.path.exists(os.path.dirname(DEST_PATH)):
+ os.makedirs(os.path.dirname(DEST_PATH))
+ shutil.copyfile(SOURCE_PATH, DEST_PATH)
diff --git a/media/mtransport/third_party/moz.build b/media/mtransport/third_party/moz.build
new file mode 100644
index 000000000..4d4013819
--- /dev/null
+++ b/media/mtransport/third_party/moz.build
@@ -0,0 +1,76 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include('/build/gyp.mozbuild')
+
+GYP_DIRS += [
+ 'nICEr',
+ 'nrappkit',
+]
+
+# These files cannot be built in unified mode because of name clashes on RCSSTRING
+nICEr_non_unified_sources = [
+ 'nICEr/src/crypto/nr_crypto.c',
+ 'nICEr/src/ice/ice_candidate.c',
+ 'nICEr/src/ice/ice_candidate_pair.c',
+ 'nICEr/src/ice/ice_component.c',
+ 'nICEr/src/ice/ice_ctx.c',
+ 'nICEr/src/ice/ice_media_stream.c',
+ 'nICEr/src/ice/ice_parser.c',
+ 'nICEr/src/ice/ice_peer_ctx.c',
+ 'nICEr/src/ice/ice_socket.c',
+ 'nICEr/src/net/nr_socket.c',
+ 'nICEr/src/net/transport_addr.c',
+ 'nICEr/src/net/transport_addr_reg.c',
+ 'nICEr/src/stun/addrs.c',
+ 'nICEr/src/stun/nr_socket_turn.c',
+ 'nICEr/src/stun/stun_build.c',
+ 'nICEr/src/stun/stun_client_ctx.c',
+ 'nICEr/src/stun/stun_codec.c',
+ 'nICEr/src/stun/stun_hint.c',
+ 'nICEr/src/stun/stun_msg.c',
+ 'nICEr/src/stun/stun_proc.c',
+ 'nICEr/src/stun/stun_server_ctx.c',
+ 'nICEr/src/stun/stun_util.c',
+ 'nICEr/src/stun/turn_client_ctx.c',
+ 'nICEr/src/util/cb_args.c',
+ 'nICEr/src/util/ice_util.c',
+]
+
+# This file cannot be built in unified mode because it breaks Linux ASAN builds
+nICEr_non_unified_sources += [
+ 'nICEr/src/util/mbslen.c',
+]
+nrappkit_non_unified_sources = [
+ 'nrappkit/src/log/r_log.c',
+ 'nrappkit/src/util/byteorder.c',
+ 'nrappkit/src/util/hex.c',
+ 'nrappkit/src/util/libekr/debug.c',
+ 'nrappkit/src/util/libekr/r_assoc.c',
+ 'nrappkit/src/util/libekr/r_crc32.c',
+ 'nrappkit/src/util/libekr/r_data.c',
+ 'nrappkit/src/util/libekr/r_errors.c',
+ 'nrappkit/src/util/libekr/r_list.c',
+ 'nrappkit/src/util/libekr/r_memory.c',
+ 'nrappkit/src/util/libekr/r_replace.c',
+ 'nrappkit/src/util/libekr/r_time.c',
+ 'nrappkit/src/util/p_buf.c',
+ 'nrappkit/src/util/util.c',
+]
+
+GYP_DIRS['nICEr'].input = 'nICEr/nicer.gyp'
+GYP_DIRS['nICEr'].variables = gyp_vars
+# We allow warnings for third-party code that can be updated from upstream.
+GYP_DIRS['nICEr'].sandbox_vars['ALLOW_COMPILER_WARNINGS'] = True
+GYP_DIRS['nICEr'].sandbox_vars['FINAL_LIBRARY'] = 'webrtc'
+GYP_DIRS['nICEr'].non_unified_sources += nICEr_non_unified_sources
+
+GYP_DIRS['nrappkit'].input = 'nrappkit/nrappkit.gyp'
+GYP_DIRS['nrappkit'].variables = gyp_vars
+# We allow warnings for third-party code that can be updated from upstream.
+GYP_DIRS['nrappkit'].sandbox_vars['ALLOW_COMPILER_WARNINGS'] = True
+GYP_DIRS['nrappkit'].sandbox_vars['FINAL_LIBRARY'] = 'webrtc'
+GYP_DIRS['nrappkit'].non_unified_sources += nrappkit_non_unified_sources
diff --git a/media/mtransport/third_party/nICEr/IMPORT_FILES b/media/mtransport/third_party/nICEr/IMPORT_FILES
new file mode 100644
index 000000000..4b30b2141
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/IMPORT_FILES
@@ -0,0 +1,71 @@
+ # Crypto
+ ./src/crypto/nr_crypto.c
+ ./src/crypto/nr_crypto.h
+ #./src/crypto/nr_crypto_openssl.c
+ #./src/crypto/nr_crypto_openssl.h
+
+ # ICE
+ ./src/ice/ice_candidate.c
+ ./src/ice/ice_candidate.h
+ ./src/ice/ice_candidate_pair.c
+ ./src/ice/ice_candidate_pair.h
+ ./src/ice/ice_codeword.h
+ ./src/ice/ice_component.c
+ ./src/ice/ice_component.h
+ ./src/ice/ice_ctx.c
+ ./src/ice/ice_ctx.h
+ ./src/ice/ice_handler.h
+ ./src/ice/ice_media_stream.c
+ ./src/ice/ice_media_stream.h
+ ./src/ice/ice_parser.c
+ ./src/ice/ice_peer_ctx.c
+ ./src/ice/ice_peer_ctx.h
+ ./src/ice/ice_reg.h
+ ./src/ice/ice_socket.c
+ ./src/ice/ice_socket.h
+
+ # Net
+ ./src/net/nr_socket.c
+ ./src/net/nr_socket.h
+ #./src/net/nr_socket_local.c
+ ./src/net/nr_socket_local.h
+ ./src/net/transport_addr.c
+ ./src/net/transport_addr.h
+ ./src/net/transport_addr_reg.c
+ ./src/net/transport_addr_reg.h
+
+ # STUN
+ ./src/stun/addrs.c
+ ./src/stun/addrs.h
+ ./src/stun/ifaddrs-android.c
+ ./src/stun/ifaddrs-android.h
+ ./src/stun/nr_socket_turn.c
+ ./src/stun/nr_socket_turn.h
+ ./src/stun/stun.h
+ ./src/stun/stun_build.c
+ ./src/stun/stun_build.h
+ ./src/stun/stun_client_ctx.c
+ ./src/stun/stun_client_ctx.h
+ ./src/stun/stun_codec.c
+ ./src/stun/stun_codec.h
+ ./src/stun/stun_hint.c
+ ./src/stun/stun_hint.h
+ ./src/stun/stun_msg.c
+ ./src/stun/stun_msg.h
+ ./src/stun/stun_proc.c
+ ./src/stun/stun_proc.h
+ ./src/stun/stun_reg.h
+ ./src/stun/stun_server_ctx.c
+ ./src/stun/stun_server_ctx.h
+ ./src/stun/stun_util.c
+ ./src/stun/stun_util.h
+ ./src/stun/turn_client_ctx.c
+ ./src/stun/turn_client_ctx.h
+
+ # Util
+ ./src/util/cb_args.c
+ ./src/util/cb_args.h
+ ./src/util/ice_util.c
+ ./src/util/ice_util.h
+ ./src/util/mbslen.c
+ ./src/util/mbslen.h
diff --git a/media/mtransport/third_party/nICEr/README b/media/mtransport/third_party/nICEr/README
new file mode 100644
index 000000000..390203dec
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/README
@@ -0,0 +1,74 @@
+ nICEr 1.0
+
+PREREQUISITES:
+-------------
+You must first obtain and build the following packages:
+
+* nrappkit
+ - http://nrappkit.sourceforge.net/
+
+* OpenSSL-0.9.8g
+ - http://www.openssl.org/source/openssl-0.9.8g.tar.gz
+
+
+For best results, the "ice-<version>" directory should be at
+the same level as the "nrappkit" and "openssl-0.9.8g"
+directories. I.e., the directory structure should look like:
+
+ nrappkit/
+ ice-<version>/
+ openssl/
+ include/
+ lib/VC/
+
+
+BUILDING ON UNIX:
+----------------
+Once the prerequisite packages are built, 'cd' to the
+relevant build directory, one of:
+
+ ice-<version>/make/darwin
+ ice-<version>/make/linux-fedora
+ ice-<version>/make/ubuntu
+
+and simply do a "make".
+
+
+BUILDING ON WINDOWS:
+-------------------
+The Visual C++ project files are configured to expect the
+directory structure described above.
+
+Note: Binary Windows builds of OpenSSL can be found at:
+ http://www.slproweb.com/products/Win32OpenSSL.html
+
+Once the prerequisite packages are built, open the VC++ 9.0
+solution file: ICE/make/win32/ice.sln and build the solution.
+Note: Since the VC++ project/solution files are version 9.0,
+Visual Studio 2008 is required.
+
+
+STATUS:
+------
+The ICE code has been tested on the following platforms:
+-- Fedora Core 4 (Intel 32-bit)
+-- Fedora Core 6 (Intel 32-bit)
+-- Ubuntu 6.10
+-- MacOSX 10.4.9
+-- Windows Vista (Home Premium)
+-- Windows XP Pro
+-- Windows 2000 SP4
+
+
+KNOWN ISSUES:
+------------
+-- TURN SET-ACTIVE-DESTINATION mode not yet supported.
+
+-- Problems may exist with the TURN client implementation; the TURN code
+ has received minimal testing due to the unavailability of a real
+ TURN server to test against.
+
+-- The ICE-Lite implementation is not complete.
+
+-- The new "impatient" timeout has not yet been thoroughly tested.
+
diff --git a/media/mtransport/third_party/nICEr/README_MOZILLA b/media/mtransport/third_party/nICEr/README_MOZILLA
new file mode 100644
index 000000000..8e058ac7d
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/README_MOZILLA
@@ -0,0 +1,11 @@
+This code was imported from:
+
+https://svn.resiprocate.org/rep/resiprocate/main/nICEr
+
+SVN revision 9873
+
+Some minor changes have been made to improve portability as well
+as to add trickle ICE. These changes are being submitted for
+upstreaming and can be found in upstream.diff.
+
+
diff --git a/media/mtransport/third_party/nICEr/nicer.gyp b/media/mtransport/third_party/nICEr/nicer.gyp
new file mode 100644
index 000000000..9df4a4b28
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/nicer.gyp
@@ -0,0 +1,254 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# nrappkit.gyp
+#
+#
+{
+ 'variables' : {
+ 'build_with_gonk%': 0,
+ 'have_ethtool_cmd_speed_hi%': 1
+ },
+ 'targets' : [
+ {
+ 'target_name' : 'nicer',
+ 'type' : 'static_library',
+
+ 'include_dirs' : [
+ ## EXTERNAL
+ # nrappkit
+ '../nrappkit/src/event',
+ '../nrappkit/src/log',
+ '../nrappkit/src/plugin',
+ '../nrappkit/src/registry',
+ '../nrappkit/src/share',
+ '../nrappkit/src/stats',
+ '../nrappkit/src/util',
+ '../nrappkit/src/util/libekr',
+ '../nrappkit/src/port/generic/include',
+
+ # INTERNAL
+ "./src/crypto",
+ "./src/ice",
+ "./src/net",
+ "./src/stun",
+ "./src/util",
+ ],
+
+ 'sources' : [
+ # Crypto
+ "./src/crypto/nr_crypto.c",
+ "./src/crypto/nr_crypto.h",
+ #"./src/crypto/nr_crypto_openssl.c",
+ #"./src/crypto/nr_crypto_openssl.h",
+
+ # ICE
+ "./src/ice/ice_candidate.c",
+ "./src/ice/ice_candidate.h",
+ "./src/ice/ice_candidate_pair.c",
+ "./src/ice/ice_candidate_pair.h",
+ "./src/ice/ice_codeword.h",
+ "./src/ice/ice_component.c",
+ "./src/ice/ice_component.h",
+ "./src/ice/ice_ctx.c",
+ "./src/ice/ice_ctx.h",
+ "./src/ice/ice_handler.h",
+ "./src/ice/ice_media_stream.c",
+ "./src/ice/ice_media_stream.h",
+ "./src/ice/ice_parser.c",
+ "./src/ice/ice_peer_ctx.c",
+ "./src/ice/ice_peer_ctx.h",
+ "./src/ice/ice_reg.h",
+ "./src/ice/ice_socket.c",
+ "./src/ice/ice_socket.h",
+
+ # Net
+ "./src/net/nr_resolver.c",
+ "./src/net/nr_resolver.h",
+ "./src/net/nr_socket_wrapper.c",
+ "./src/net/nr_socket_wrapper.h",
+ "./src/net/nr_proxy_tunnel.c",
+ "./src/net/nr_proxy_tunnel.h",
+ "./src/net/nr_socket.c",
+ "./src/net/nr_socket.h",
+ #"./src/net/nr_socket_local.c",
+ "./src/net/nr_socket_local.h",
+ "./src/net/nr_socket_multi_tcp.c",
+ "./src/net/nr_socket_multi_tcp.h",
+ "./src/net/transport_addr.c",
+ "./src/net/transport_addr.h",
+ "./src/net/transport_addr_reg.c",
+ "./src/net/transport_addr_reg.h",
+ "./src/net/local_addr.c",
+ "./src/net/local_addr.h",
+ "./src/net/nr_interface_prioritizer.c",
+ "./src/net/nr_interface_prioritizer.h",
+
+ # STUN
+ "./src/stun/addrs.c",
+ "./src/stun/addrs.h",
+ "./src/stun/ifaddrs-android.c",
+ "./src/stun/ifaddrs-android.h",
+ "./src/stun/nr_socket_turn.c",
+ "./src/stun/nr_socket_turn.h",
+ "./src/stun/nr_socket_buffered_stun.c",
+ "./src/stun/nr_socket_buffered_stun.h",
+ "./src/stun/stun.h",
+ "./src/stun/stun_build.c",
+ "./src/stun/stun_build.h",
+ "./src/stun/stun_client_ctx.c",
+ "./src/stun/stun_client_ctx.h",
+ "./src/stun/stun_codec.c",
+ "./src/stun/stun_codec.h",
+ "./src/stun/stun_hint.c",
+ "./src/stun/stun_hint.h",
+ "./src/stun/stun_msg.c",
+ "./src/stun/stun_msg.h",
+ "./src/stun/stun_proc.c",
+ "./src/stun/stun_proc.h",
+ "./src/stun/stun_reg.h",
+ "./src/stun/stun_server_ctx.c",
+ "./src/stun/stun_server_ctx.h",
+ "./src/stun/stun_util.c",
+ "./src/stun/stun_util.h",
+ "./src/stun/turn_client_ctx.c",
+ "./src/stun/turn_client_ctx.h",
+
+ # Util
+ "./src/util/cb_args.c",
+ "./src/util/cb_args.h",
+ "./src/util/ice_util.c",
+ "./src/util/ice_util.h",
+ "./src/util/mbslen.c",
+ "./src/util/mbslen.h",
+
+
+ ],
+
+ 'defines' : [
+ 'SANITY_CHECKS',
+ 'USE_TURN',
+ 'USE_ICE',
+ 'USE_RFC_3489_BACKWARDS_COMPATIBLE',
+ 'USE_STUND_0_96',
+ 'USE_STUN_PEDANTIC',
+ 'USE_TURN',
+ 'NR_SOCKET_IS_VOID_PTR',
+ 'restrict=',
+ 'R_PLATFORM_INT_TYPES=<stdint.h>',
+ 'R_DEFINED_INT2=int16_t',
+ 'R_DEFINED_UINT2=uint16_t',
+ 'R_DEFINED_INT4=int32_t',
+ 'R_DEFINED_UINT4=uint32_t',
+ 'R_DEFINED_INT8=int64_t',
+ 'R_DEFINED_UINT8=uint64_t',
+ ],
+
+ 'conditions' : [
+ ## Mac and BSDs
+ [ 'OS == "mac" or OS == "ios"', {
+ 'defines' : [
+ 'DARWIN',
+ ],
+ }],
+ [ 'os_bsd == 1', {
+ 'defines' : [
+ 'BSD',
+ ],
+ }],
+ [ 'OS == "mac" or OS == "ios" or os_bsd == 1', {
+ 'cflags_mozilla': [
+ '-Wall',
+ '-Wno-parentheses',
+ '-Wno-strict-prototypes',
+ '-Wmissing-prototypes',
+ ],
+ 'defines' : [
+ 'HAVE_LIBM=1',
+ 'HAVE_STRDUP=1',
+ 'HAVE_STRLCPY=1',
+ 'HAVE_SYS_TIME_H=1',
+ 'HAVE_VFPRINTF=1',
+ 'NEW_STDIO'
+ 'RETSIGTYPE=void',
+ 'TIME_WITH_SYS_TIME_H=1',
+ '__UNUSED__=__attribute__((unused))',
+ ],
+
+ 'include_dirs': [
+ '../nrappkit/src/port/darwin/include'
+ ],
+
+ 'sources': [
+ ],
+ }],
+
+ ## Win
+ [ 'OS == "win"', {
+ 'defines' : [
+ 'WIN32',
+ 'USE_ICE',
+ 'USE_TURN',
+ 'USE_RFC_3489_BACKWARDS_COMPATIBLE',
+ 'USE_STUND_0_96',
+ 'USE_STUN_PEDANTIC',
+ '_CRT_SECURE_NO_WARNINGS',
+ '__UNUSED__=',
+ 'HAVE_STRDUP',
+ 'NO_REG_RPC'
+ ],
+
+ 'include_dirs': [
+ '../nrappkit/src/port/win32/include'
+ ],
+ }],
+ ## Linux/Android
+ [ '(OS == "linux") or (OS=="android")', {
+ 'cflags_mozilla': [
+ '-Wall',
+ '-Wno-parentheses',
+ '-Wno-strict-prototypes',
+ '-Wmissing-prototypes',
+ ],
+ 'defines' : [
+ 'LINUX',
+ 'HAVE_LIBM=1',
+ 'HAVE_STRDUP=1',
+ 'HAVE_STRLCPY=1',
+ 'HAVE_SYS_TIME_H=1',
+ 'HAVE_VFPRINTF=1',
+ 'NEW_STDIO'
+ 'RETSIGTYPE=void',
+ 'TIME_WITH_SYS_TIME_H=1',
+ '__UNUSED__=__attribute__((unused))',
+ ],
+
+ 'include_dirs': [
+ '../nrappkit/src/port/linux/include'
+ ],
+
+ 'sources': [
+ ],
+ }],
+ ['moz_widget_toolkit_gonk==1', {
+ 'defines' : [
+ 'WEBRTC_GONK',
+ 'NO_REG_RPC',
+ ],
+ }],
+ # Gonk has its own nr_stun_get_addrs implementation.
+ ['build_with_gonk==1', {
+ 'defines': [
+ "USE_PLATFORM_NR_STUN_GET_ADDRS",
+ ]
+ }],
+ ['have_ethtool_cmd_speed_hi==0', {
+ 'defines': [
+ "DONT_HAVE_ETHTOOL_SPEED_HI",
+ ]
+ }]
+ ],
+ }]
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.c b/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.c
new file mode 100644
index 000000000..088ebf045
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.c
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: nr_crypto.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <nr_api.h>
+#include "nr_crypto.h"
+
+static int nr_ice_crypto_dummy_random_bytes(UCHAR *buf, int len)
+ {
+ fprintf(stderr,"Need to define crypto API implementation\n");
+
+ exit(1);
+ }
+
+static int nr_ice_crypto_dummy_hmac_sha1(UCHAR *key, int key_l, UCHAR *buf, int buf_l, UCHAR digest[20])
+ {
+ fprintf(stderr,"Need to define crypto API implementation\n");
+
+ exit(1);
+ }
+
+static int nr_ice_crypto_dummy_md5(UCHAR *buf, int buf_l, UCHAR digest[16])
+ {
+ fprintf(stderr,"Need to define crypto API implementation\n");
+
+ exit(1);
+ }
+
+static nr_ice_crypto_vtbl nr_ice_crypto_dummy_vtbl= {
+ nr_ice_crypto_dummy_random_bytes,
+ nr_ice_crypto_dummy_hmac_sha1,
+ nr_ice_crypto_dummy_md5
+};
+
+
+
+nr_ice_crypto_vtbl *nr_crypto_vtbl=&nr_ice_crypto_dummy_vtbl;
+
+
diff --git a/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.h b/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.h
new file mode 100644
index 000000000..4c71786f0
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/crypto/nr_crypto.h
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _nr_crypto_h
+#define _nr_crypto_h
+
+
+typedef struct nr_ice_crypto_vtbl_ {
+ int (*random_bytes)(UCHAR *buf, int len);
+ int (*hmac_sha1)(UCHAR *key, int key_l, UCHAR *buf, int buf_l, UCHAR digest[20]);
+ int (*md5)(UCHAR *buf, int buf_l, UCHAR digest[16]);
+} nr_ice_crypto_vtbl;
+
+extern nr_ice_crypto_vtbl *nr_crypto_vtbl;
+
+#define nr_crypto_random_bytes(a,b) nr_crypto_vtbl->random_bytes(a,b)
+#define nr_crypto_hmac_sha1(a,b,c,d,e) nr_crypto_vtbl->hmac_sha1(a,b,c,d,e)
+#define nr_crypto_md5(a,b,c) nr_crypto_vtbl->md5(a,b,c)
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c
new file mode 100644
index 000000000..e48b7b5e1
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c
@@ -0,0 +1,979 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_candidate.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <csi_platform.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "nr_api.h"
+#include "registry.h"
+#include "nr_socket.h"
+#include "async_timer.h"
+
+#include "stun_client_ctx.h"
+#include "stun_server_ctx.h"
+#include "turn_client_ctx.h"
+#include "ice_ctx.h"
+#include "ice_candidate.h"
+#include "ice_codeword.h"
+#include "ice_reg.h"
+#include "ice_util.h"
+#include "nr_socket_turn.h"
+#include "nr_socket.h"
+#include "nr_socket_multi_tcp.h"
+
+static int next_automatic_preference = 127;
+
+static int nr_ice_candidate_initialize2(nr_ice_candidate *cand);
+static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
+static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand);
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg);
+#ifdef USE_TURN
+static int nr_ice_start_relay_turn(nr_ice_candidate *cand);
+static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg);
+static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr);
+#endif /* USE_TURN */
+
+void nr_ice_candidate_compute_codeword(nr_ice_candidate *cand)
+ {
+ char as_string[1024];
+
+ snprintf(as_string,
+ sizeof(as_string),
+ "%s(%s)",
+ cand->addr.as_string,
+ cand->label);
+
+ nr_ice_compute_codeword(as_string,strlen(as_string),cand->codeword);
+ }
+
+char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
+char *nr_ice_candidate_tcp_type_names[]={0,"active","passive","so",0};
+
+static const char *nr_ctype_name(nr_ice_candidate_type ctype) {
+ assert(ctype<CTYPE_MAX && ctype>0);
+ if (ctype <= 0 || ctype >= CTYPE_MAX) {
+ return "ERROR";
+ }
+ return nr_ice_candidate_type_names[ctype];
+}
+
+static const char *nr_tcp_type_name(nr_socket_tcp_type tcp_type) {
+ assert(tcp_type<TCP_TYPE_MAX && tcp_type>0);
+ if (tcp_type <= 0 || tcp_type >= TCP_TYPE_MAX) {
+ return "ERROR";
+ }
+ return nr_ice_candidate_tcp_type_names[tcp_type];
+}
+
+static int nr_ice_candidate_format_stun_label(char *label, size_t size, nr_ice_candidate *cand)
+ {
+ int _status;
+
+ *label = 0;
+ switch(cand->stun_server->type) {
+ case NR_ICE_STUN_SERVER_TYPE_ADDR:
+ snprintf(label, size, "%s(%s|%s)", nr_ctype_name(cand->type), cand->base.as_string,
+ cand->stun_server->u.addr.as_string);
+ break;
+ case NR_ICE_STUN_SERVER_TYPE_DNSNAME:
+ snprintf(label, size, "%s(%s|%s:%u)", nr_ctype_name(cand->type), cand->base.as_string,
+ cand->stun_server->u.dnsname.host, cand->stun_server->u.dnsname.port);
+ break;
+ default:
+ assert(0);
+ ABORT(R_BAD_ARGS);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_candidate_create(nr_ice_ctx *ctx,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_socket_tcp_type tcp_type, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp)
+ {
+ assert(!(ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) || ctype == RELAYED);
+ nr_ice_candidate *cand=0;
+ nr_ice_candidate *tmp=0;
+ int r,_status;
+ char label[512];
+
+ if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
+ ABORT(R_NO_MEMORY);
+ cand->state=NR_ICE_CAND_STATE_CREATED;
+ cand->ctx=ctx;
+ cand->isock=isock;
+ cand->osock=osock;
+ cand->type=ctype;
+ cand->tcp_type=tcp_type;
+ cand->stun_server=stun_server;
+ cand->component_id=component_id;
+ cand->component=comp;
+ cand->stream=comp->stream;
+
+ /* Extract the addr as the base */
+ if(r=nr_socket_getaddr(cand->isock->sock,&cand->base))
+ ABORT(r);
+
+ switch(ctype) {
+ case HOST:
+ snprintf(label, sizeof(label), "host(%s)", cand->base.as_string);
+ break;
+
+ case SERVER_REFLEXIVE:
+ if(r=nr_ice_candidate_format_stun_label(label, sizeof(label), cand))
+ ABORT(r);
+ break;
+
+ case RELAYED:
+ if(r=nr_ice_candidate_format_stun_label(label, sizeof(label), cand))
+ ABORT(r);
+ break;
+
+ case PEER_REFLEXIVE:
+ snprintf(label, sizeof(label), "prflx");
+ break;
+
+ default:
+ assert(0); /* Can't happen */
+ ABORT(R_BAD_ARGS);
+ }
+
+ if (tcp_type) {
+ const char* ttype = nr_tcp_type_name(tcp_type);
+ const int tlen = strlen(ttype)+1; /* plus space */
+ const size_t llen=strlen(label);
+ if (snprintf(label+llen, sizeof(label)-llen, " %s", ttype) != tlen) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): truncated tcp type added to buffer",
+ ctx->label);
+ }
+ }
+
+ if(!(cand->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ if(r=nr_ice_get_foundation(ctx,cand))
+ ABORT(r);
+ if(r=nr_ice_candidate_compute_priority(cand))
+ ABORT(r);
+
+ TAILQ_FOREACH(tmp,&isock->candidates,entry_sock){
+ if(cand->priority==tmp->priority){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): duplicate priority %u candidate %s and candidate %s",
+ ctx->label,cand->priority,cand->label,tmp->label);
+ }
+ }
+
+ if(ctype==RELAYED)
+ cand->u.relayed.turn_sock=osock;
+
+
+ /* Add the candidate to the isock list*/
+ TAILQ_INSERT_TAIL(&isock->candidates,cand,entry_sock);
+
+ nr_ice_candidate_compute_codeword(cand);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): created candidate %s with type %s",
+ ctx->label,cand->codeword,cand->label,nr_ctype_name(ctype));
+
+ *candp=cand;
+
+ _status=0;
+ abort:
+ if (_status){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): Failed to create candidate of type %s", ctx->label,nr_ctype_name(ctype));
+ nr_ice_candidate_destroy(&cand);
+ }
+ return(_status);
+ }
+
+
+/* Create a peer reflexive candidate */
+int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp)
+ {
+ nr_ice_candidate *cand=0;
+ nr_ice_candidate_type ctype=PEER_REFLEXIVE;
+ int r,_status;
+
+ if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
+ ABORT(R_NO_MEMORY);
+ if(!(cand->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ cand->state=NR_ICE_CAND_STATE_INITIALIZED;
+ cand->ctx=ctx;
+ cand->type=ctype;
+ cand->component_id=comp->component_id;
+ cand->component=comp;
+ cand->stream=comp->stream;
+
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): creating candidate with type %s",
+ ctx->label,label,nr_ctype_name(ctype));
+
+ if(r=nr_transport_addr_copy(&cand->base,addr))
+ ABORT(r);
+ if(r=nr_transport_addr_copy(&cand->addr,addr))
+ ABORT(r);
+ /* Bogus foundation */
+ if(!(cand->foundation=r_strdup(cand->addr.as_string)))
+ ABORT(R_NO_MEMORY);
+
+ nr_ice_candidate_compute_codeword(cand);
+
+ *candp=cand;
+
+ _status=0;
+ abort:
+ if (_status){
+ nr_ice_candidate_destroy(&cand);
+ }
+ return(_status);
+ }
+
+static void nr_ice_candidate_mark_done(nr_ice_candidate *cand, int state)
+ {
+ if (!cand || !cand->done_cb) {
+ assert(0);
+ return;
+ }
+
+ /* If this is a relay candidate, there's likely to be a srflx that is
+ * piggybacking on it. Make sure it is marked done too. */
+ if ((cand->type == RELAYED) && cand->u.relayed.srvflx_candidate) {
+ nr_ice_candidate *srflx=cand->u.relayed.srvflx_candidate;
+ if (state == NR_ICE_CAND_STATE_INITIALIZED &&
+ nr_turn_client_get_mapped_address(cand->u.relayed.turn,
+ &srflx->addr)) {
+ r_log(LOG_ICE, LOG_WARNING, "ICE(%s)/CAND(%s): Failed to get mapped address from TURN allocate response, srflx failed.", cand->ctx->label, cand->label);
+ nr_ice_candidate_mark_done(srflx, NR_ICE_CAND_STATE_FAILED);
+ } else {
+ nr_ice_candidate_mark_done(srflx, state);
+ }
+ }
+
+ NR_async_cb done_cb=cand->done_cb;
+ cand->done_cb=0;
+ cand->state=state;
+ /* This might destroy cand! */
+ done_cb(0,0,cand->cb_arg);
+ }
+
+int nr_ice_candidate_destroy(nr_ice_candidate **candp)
+ {
+ nr_ice_candidate *cand=0;
+
+ if(!candp || !*candp)
+ return(0);
+
+ cand=*candp;
+
+ if (cand->state == NR_ICE_CAND_STATE_INITIALIZING) {
+ /* Make sure the ICE ctx isn't still waiting around for this candidate
+ * to init. */
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED);
+ }
+
+ switch(cand->type){
+ case HOST:
+ break;
+#ifdef USE_TURN
+ case RELAYED:
+ if (cand->u.relayed.turn_handle)
+ nr_ice_socket_deregister(cand->isock, cand->u.relayed.turn_handle);
+ if (cand->u.relayed.srvflx_candidate)
+ cand->u.relayed.srvflx_candidate->u.srvrflx.relay_candidate=0;
+ nr_turn_client_ctx_destroy(&cand->u.relayed.turn);
+ nr_socket_destroy(&cand->u.relayed.turn_sock);
+ break;
+#endif /* USE_TURN */
+ case SERVER_REFLEXIVE:
+ if (cand->u.srvrflx.stun_handle)
+ nr_ice_socket_deregister(cand->isock, cand->u.srvrflx.stun_handle);
+ if (cand->u.srvrflx.relay_candidate)
+ cand->u.srvrflx.relay_candidate->u.relayed.srvflx_candidate=0;
+ nr_stun_client_ctx_destroy(&cand->u.srvrflx.stun);
+ break;
+ default:
+ break;
+ }
+
+ NR_async_timer_cancel(cand->delay_timer);
+ NR_async_timer_cancel(cand->ready_cb_timer);
+ if(cand->resolver_handle){
+ nr_resolver_cancel(cand->ctx->resolver,cand->resolver_handle);
+ }
+
+ RFREE(cand->foundation);
+ RFREE(cand->label);
+ RFREE(cand);
+
+ return(0);
+ }
+
+/* This algorithm is not super-fast, but I don't think we need a hash
+ table just yet and it produces a small foundation string */
+static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand)
+ {
+ nr_ice_foundation *foundation;
+ int i=0;
+ char fnd[20];
+ int _status;
+
+ foundation=STAILQ_FIRST(&ctx->foundations);
+ while(foundation){
+ if(nr_transport_addr_cmp(&cand->base,&foundation->addr,NR_TRANSPORT_ADDR_CMP_MODE_ADDR))
+ goto next;
+ if(cand->type != foundation->type)
+ goto next;
+ if(cand->stun_server != foundation->stun_server)
+ goto next;
+
+ snprintf(fnd,sizeof(fnd),"%d",i);
+ if(!(cand->foundation=r_strdup(fnd)))
+ ABORT(R_NO_MEMORY);
+ return(0);
+
+ next:
+ foundation=STAILQ_NEXT(foundation,entry);
+ i++;
+ }
+
+ if(!(foundation=RCALLOC(sizeof(nr_ice_foundation))))
+ ABORT(R_NO_MEMORY);
+ nr_transport_addr_copy(&foundation->addr,&cand->base);
+ foundation->type=cand->type;
+ foundation->stun_server=cand->stun_server;
+ STAILQ_INSERT_TAIL(&ctx->foundations,foundation,entry);
+
+ snprintf(fnd,sizeof(fnd),"%d",i);
+ if(!(cand->foundation=r_strdup(fnd)))
+ ABORT(R_NO_MEMORY);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_candidate_compute_priority(nr_ice_candidate *cand)
+ {
+ UCHAR type_preference;
+ UCHAR interface_preference;
+ UCHAR stun_priority;
+ UCHAR direction_priority=0;
+ int r,_status;
+
+ if (cand->base.protocol != IPPROTO_UDP && cand->base.protocol != IPPROTO_TCP){
+ r_log(LOG_ICE,LOG_ERR,"Unknown protocol type %u",
+ (unsigned int)cand->base.protocol);
+ ABORT(R_INTERNAL);
+ }
+
+ switch(cand->type){
+ case HOST:
+ if(cand->base.protocol == IPPROTO_UDP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_HOST,&type_preference))
+ ABORT(r);
+ } else if(cand->base.protocol == IPPROTO_TCP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_HOST_TCP,&type_preference))
+ ABORT(r);
+ }
+ stun_priority=0;
+ break;
+ case RELAYED:
+ if(cand->base.protocol == IPPROTO_UDP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_RELAYED,&type_preference))
+ ABORT(r);
+ } else if(cand->base.protocol == IPPROTO_TCP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_RELAYED_TCP,&type_preference))
+ ABORT(r);
+ }
+ stun_priority=31-cand->stun_server->id;
+ break;
+ case SERVER_REFLEXIVE:
+ if(cand->base.protocol == IPPROTO_UDP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_SRV_RFLX,&type_preference))
+ ABORT(r);
+ } else if(cand->base.protocol == IPPROTO_TCP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP,&type_preference))
+ ABORT(r);
+ }
+ stun_priority=31-cand->stun_server->id;
+ break;
+ case PEER_REFLEXIVE:
+ if(cand->base.protocol == IPPROTO_UDP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_PEER_RFLX,&type_preference))
+ ABORT(r);
+ } else if(cand->base.protocol == IPPROTO_TCP) {
+ if(r=NR_reg_get_uchar(NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP,&type_preference))
+ ABORT(r);
+ }
+ stun_priority=0;
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ if(cand->base.protocol == IPPROTO_TCP){
+ switch (cand->tcp_type) {
+ case TCP_TYPE_ACTIVE:
+ if (cand->type == HOST)
+ direction_priority=6;
+ else
+ direction_priority=4;
+ break;
+ case TCP_TYPE_PASSIVE:
+ if (cand->type == HOST)
+ direction_priority=4;
+ else
+ direction_priority=2;
+ break;
+ case TCP_TYPE_SO:
+ if (cand->type == HOST)
+ direction_priority=2;
+ else
+ direction_priority=6;
+ break;
+ case TCP_TYPE_NONE:
+ break;
+ case TCP_TYPE_MAX:
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ }
+ }
+
+ if(type_preference > 126)
+ r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
+
+ if(!cand->ctx->interface_prioritizer) {
+ /* Prioritizer is not set, read from registry */
+ if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
+ &interface_preference)) {
+ if (r==R_NOT_FOUND) {
+ if (next_automatic_preference == 1) {
+ r_log(LOG_ICE,LOG_ERR,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
+ ABORT(R_NOT_FOUND);
+ }
+ r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
+ next_automatic_preference);
+ if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
+ ABORT(r);
+ }
+ interface_preference=next_automatic_preference << 1;
+ next_automatic_preference--;
+ if (cand->base.ip_version == NR_IPV6) {
+ /* Prefer IPV6 over IPV4 on the same interface. */
+ interface_preference += 1;
+ }
+ }
+ else {
+ ABORT(r);
+ }
+ }
+ }
+ else {
+ char key_of_interface[MAXIFNAME + 41];
+ nr_transport_addr addr;
+
+ if(r=nr_socket_getaddr(cand->isock->sock, &addr))
+ ABORT(r);
+
+ if(r=nr_transport_addr_fmt_ifname_addr_string(&addr,key_of_interface,
+ sizeof(key_of_interface))) {
+ ABORT(r);
+ }
+ if(r=nr_interface_prioritizer_get_priority(cand->ctx->interface_prioritizer,
+ key_of_interface,&interface_preference)) {
+ ABORT(r);
+ }
+ }
+
+ assert(stun_priority < 32);
+ assert(direction_priority < 8);
+
+ cand->priority=
+ (type_preference << 24) |
+ (interface_preference << 16) |
+ (direction_priority << 13) |
+ (stun_priority << 8) |
+ (256 - cand->component_id);
+
+ /* S 4.1.2 */
+ assert(cand->priority>=1&&cand->priority<=2147483647);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static void nr_ice_candidate_fire_ready_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_candidate *cand = cb_arg;
+
+ cand->ready_cb_timer = 0;
+ cand->ready_cb(0, 0, cand->ready_cb_arg);
+ }
+
+int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg)
+ {
+ int r,_status;
+ int protocol=NR_RESOLVE_PROTOCOL_STUN;
+ cand->done_cb=ready_cb;
+ cand->cb_arg=cb_arg;
+ cand->state=NR_ICE_CAND_STATE_INITIALIZING;
+
+ switch(cand->type){
+ case HOST:
+ if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
+ ABORT(r);
+ cand->osock=cand->isock->sock;
+ // Post this so that it doesn't happen in-line
+ cand->ready_cb = ready_cb;
+ cand->ready_cb_arg = cb_arg;
+ NR_ASYNC_TIMER_SET(0, nr_ice_candidate_fire_ready_cb, (void *)cand, &cand->ready_cb_timer);
+ break;
+#ifdef USE_TURN
+ case RELAYED:
+ protocol=NR_RESOLVE_PROTOCOL_TURN;
+ /* Fall through */
+#endif
+ case SERVER_REFLEXIVE:
+ if(cand->stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR) {
+ if(nr_transport_addr_cmp(&cand->base,&cand->stun_server->u.addr,NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL)) {
+ r_log(LOG_ICE, LOG_INFO, "ICE-CANDIDATE(%s): Skipping srflx/relayed candidate because of IP version/transport mis-match with STUN/TURN server (%u/%s - %u/%s).", cand->label,cand->base.ip_version,cand->base.protocol==IPPROTO_UDP?"UDP":"TCP",cand->stun_server->u.addr.ip_version,cand->stun_server->u.addr.protocol==IPPROTO_UDP?"UDP":"TCP");
+ ABORT(R_NOT_FOUND); /* Same error code when DNS lookup fails */
+ }
+
+ /* Just copy the address */
+ if (r=nr_transport_addr_copy(&cand->stun_server_addr,
+ &cand->stun_server->u.addr)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE-CANDIDATE(%s): Could not copy STUN server addr", cand->label);
+ ABORT(r);
+ }
+
+ if(r=nr_ice_candidate_initialize2(cand))
+ ABORT(r);
+ }
+ else {
+ nr_resolver_resource resource;
+ resource.domain_name=cand->stun_server->u.dnsname.host;
+ resource.port=cand->stun_server->u.dnsname.port;
+ resource.stun_turn=protocol;
+ resource.transport_protocol=cand->stun_server->transport;
+
+ switch (cand->base.ip_version) {
+ case NR_IPV4:
+ resource.address_family=AF_INET;
+ break;
+ case NR_IPV6:
+ resource.address_family=AF_INET6;
+ break;
+ default:
+ ABORT(R_BAD_ARGS);
+ }
+
+ /* Try to resolve */
+ if(!cand->ctx->resolver) {
+ r_log(LOG_ICE, LOG_ERR, "ICE-CANDIDATE(%s): Can't use DNS names without a resolver", cand->label);
+ ABORT(R_BAD_ARGS);
+ }
+
+ if(r=nr_resolver_resolve(cand->ctx->resolver,
+ &resource,
+ nr_ice_candidate_resolved_cb,
+ (void *)cand,
+ &cand->resolver_handle)){
+ r_log(LOG_ICE,LOG_ERR,"ICE-CANDIDATE(%s): Could not invoke DNS resolver",cand->label);
+ ABORT(r);
+ }
+ }
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ nr_ice_candidate_compute_codeword(cand);
+
+ _status=0;
+ abort:
+ if(_status && _status!=R_WOULDBLOCK)
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED);
+ return(_status);
+ }
+
+
+static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ int r,_status;
+
+ cand->resolver_handle=0;
+
+ if(addr){
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): resolved candidate %s. addr=%s",
+ cand->ctx->label,cand->label,addr->as_string);
+ }
+ else {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): failed to resolve candidate %s.",
+ cand->ctx->label,cand->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ /* Copy the address */
+ if(r=nr_transport_addr_copy(&cand->stun_server_addr,addr))
+ ABORT(r);
+
+ if (cand->tcp_type == TCP_TYPE_PASSIVE || cand->tcp_type == TCP_TYPE_SO){
+ if (r=nr_socket_multi_tcp_stun_server_connect(cand->osock, addr))
+ ABORT(r);
+ }
+
+ /* Now start initializing */
+ if(r=nr_ice_candidate_initialize2(cand))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if(_status && _status!=R_WOULDBLOCK) {
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED);
+ }
+ return(_status);
+ }
+
+static int nr_ice_candidate_initialize2(nr_ice_candidate *cand)
+ {
+ int r,_status;
+
+ switch(cand->type){
+ case HOST:
+ assert(0); /* Can't happen */
+ ABORT(R_INTERNAL);
+ break;
+#ifdef USE_TURN
+ case RELAYED:
+ if(r=nr_ice_start_relay_turn(cand))
+ ABORT(r);
+ ABORT(R_WOULDBLOCK);
+ break;
+#endif /* USE_TURN */
+ case SERVER_REFLEXIVE:
+ /* Need to start stun */
+ if(r=nr_ice_srvrflx_start_stun(cand))
+ ABORT(r);
+ cand->osock=cand->isock->sock;
+ ABORT(R_WOULDBLOCK);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ int r,_status;
+
+ cand->delay_timer=0;
+
+/* TODO: if the response is a BINDING-ERROR-RESPONSE, then restart
+ * TODO: using NR_STUN_CLIENT_MODE_BINDING_REQUEST because the
+ * TODO: server may not have understood the 0.96-style request */
+ if(r=nr_stun_client_start(cand->u.srvrflx.stun, NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH, nr_ice_srvrflx_stun_finished_cb, cand))
+ ABORT(r);
+
+ if(r=nr_ice_ctx_remember_id(cand->ctx, cand->u.srvrflx.stun->request))
+ ABORT(r);
+
+ if(r=nr_ice_socket_register_stun_client(cand->isock,cand->u.srvrflx.stun,&cand->u.srvrflx.stun_handle))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (_status && (cand->u.srvrflx.stun->state==NR_STUN_CLIENT_STATE_RUNNING)) {
+ nr_stun_client_failed(cand->u.srvrflx.stun);
+ }
+ return;
+ }
+
+static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand)
+ {
+ int r,_status;
+
+ assert(!cand->delay_timer);
+ if(r=nr_stun_client_ctx_create(cand->label, cand->isock->sock,
+ &cand->stun_server_addr, cand->stream->ctx->gather_rto,
+ &cand->u.srvrflx.stun))
+ ABORT(r);
+
+ NR_ASYNC_TIMER_SET(cand->stream->ctx->stun_delay,nr_ice_srvrflx_start_stun_timer_cb,cand,&cand->delay_timer);
+ cand->stream->ctx->stun_delay += cand->stream->ctx->Ta;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+#ifdef USE_TURN
+static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ int r,_status;
+
+ cand->delay_timer=0;
+
+ if(r=nr_turn_client_allocate(cand->u.relayed.turn, nr_ice_turn_allocated_cb, cb_arg))
+ ABORT(r);
+
+ if(r=nr_ice_socket_register_turn_client(cand->isock, cand->u.relayed.turn,
+ cand->osock, &cand->u.relayed.turn_handle))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if(_status && (cand->u.relayed.turn->state==NR_TURN_CLIENT_STATE_ALLOCATING)){
+ nr_turn_client_failed(cand->u.relayed.turn);
+ }
+ return;
+ }
+
+static int nr_ice_start_relay_turn(nr_ice_candidate *cand)
+ {
+ int r,_status;
+ assert(!cand->delay_timer);
+ if(r=nr_turn_client_ctx_create(cand->label, cand->isock->sock,
+ cand->u.relayed.server->username,
+ cand->u.relayed.server->password,
+ &cand->stun_server_addr,
+ &cand->u.relayed.turn))
+ ABORT(r);
+
+ if(r=nr_socket_turn_set_ctx(cand->osock, cand->u.relayed.turn))
+ ABORT(r);
+
+ NR_ASYNC_TIMER_SET(cand->stream->ctx->stun_delay,nr_ice_start_relay_turn_timer_cb,cand,&cand->delay_timer);
+ cand->stream->ctx->stun_delay += cand->stream->ctx->Ta;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+#endif /* USE_TURN */
+
+static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg)
+ {
+ int _status;
+ nr_ice_candidate *cand=cb_arg;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): %s",cand->ctx->label,cand->label,__FUNCTION__);
+
+ /* Deregister to suppress duplicates */
+ if(cand->u.srvrflx.stun_handle){ /* This test because we might have failed before CB registered */
+ nr_ice_socket_deregister(cand->isock,cand->u.srvrflx.stun_handle);
+ cand->u.srvrflx.stun_handle=0;
+ }
+
+ switch(cand->u.srvrflx.stun->state){
+ /* OK, we should have a mapped address */
+ case NR_STUN_CLIENT_STATE_DONE:
+ /* Copy the address */
+ nr_transport_addr_copy(&cand->addr, &cand->u.srvrflx.stun->results.stun_binding_response.mapped_addr);
+ cand->addr.protocol=cand->base.protocol;
+ nr_transport_addr_fmt_addr_string(&cand->addr);
+ nr_stun_client_ctx_destroy(&cand->u.srvrflx.stun);
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_INITIALIZED);
+ cand=0;
+ break;
+
+ /* This failed, so go to the next STUN server if there is one */
+ case NR_STUN_CLIENT_STATE_FAILED:
+ ABORT(R_NOT_FOUND);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+ _status = 0;
+ abort:
+ if(_status){
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED);
+ }
+ }
+
+#ifdef USE_TURN
+static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_candidate *cand=cb_arg;
+ nr_turn_client_ctx *turn=cand->u.relayed.turn;
+ char *label;
+ nr_transport_addr relay_addr;
+
+ switch(turn->state){
+ /* OK, we should have a mapped address */
+ case NR_TURN_CLIENT_STATE_ALLOCATED:
+ if (r=nr_turn_client_get_relayed_address(turn, &relay_addr))
+ ABORT(r);
+
+ if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",
+ relay_addr.as_string,")",NULL))
+ ABORT(r);
+
+ r_log(LOG_ICE,LOG_DEBUG,"TURN-CLIENT(%s)/CAND(%s): Switching from TURN to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
+
+ /* Copy the relayed address into the candidate addr and
+ into the candidate base. Note that we need to keep the
+ ifname in the base. */
+ if (r=nr_transport_addr_copy(&cand->addr, &relay_addr))
+ ABORT(r);
+ if (r=nr_transport_addr_copy_keep_ifname(&cand->base, &relay_addr)) /* Need to keep interface for priority calculation */
+ ABORT(r);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): new relay base=%s addr=%s", cand->ctx->label, cand->label, cand->base.as_string, cand->addr.as_string);
+
+ RFREE(cand->label);
+ cand->label=label;
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_INITIALIZED);
+ cand = 0;
+
+ break;
+
+ case NR_TURN_CLIENT_STATE_FAILED:
+ case NR_TURN_CLIENT_STATE_CANCELLED:
+ r_log(NR_LOG_TURN, LOG_WARNING,
+ "ICE-CANDIDATE(%s): nr_turn_allocated_cb called with state %d",
+ cand->label, turn->state);
+ /* This failed, so go to the next TURN server if there is one */
+ ABORT(R_NOT_FOUND);
+ break;
+ default:
+ assert(0); /* should never happen */
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ if(_status){
+ if (cand) {
+ r_log(NR_LOG_TURN, LOG_WARNING,
+ "ICE-CANDIDATE(%s): nr_turn_allocated_cb failed", cand->label);
+ nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED);
+ }
+ }
+ }
+#endif /* USE_TURN */
+
+/* Format the candidate attribute as per ICE S 15.1 */
+int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen)
+ {
+ int r,_status;
+ char addr[64];
+ int port;
+ int len;
+ nr_transport_addr *raddr;
+
+ assert(!strcmp(nr_ice_candidate_type_names[HOST], "host"));
+ assert(!strcmp(nr_ice_candidate_type_names[RELAYED], "relay"));
+
+ if(r=nr_transport_addr_get_addrstring(&cand->addr,addr,sizeof(addr)))
+ ABORT(r);
+ if(r=nr_transport_addr_get_port(&cand->addr,&port))
+ ABORT(r);
+ /* https://tools.ietf.org/html/rfc6544#section-4.5 */
+ if (cand->base.protocol==IPPROTO_TCP && cand->tcp_type==TCP_TYPE_ACTIVE)
+ port=9;
+ snprintf(attr,maxlen,"candidate:%s %d %s %u %s %d typ %s",
+ cand->foundation, cand->component_id, cand->addr.protocol==IPPROTO_UDP?"UDP":"TCP",cand->priority, addr, port,
+ nr_ctype_name(cand->type));
+
+ len=strlen(attr); attr+=len; maxlen-=len;
+
+ /* raddr, rport */
+ raddr = (cand->stream->ctx->flags &
+ (NR_ICE_CTX_FLAGS_RELAY_ONLY |
+ NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES)) ?
+ &cand->addr : &cand->base;
+
+ switch(cand->type){
+ case HOST:
+ break;
+ case SERVER_REFLEXIVE:
+ case PEER_REFLEXIVE:
+ if(r=nr_transport_addr_get_addrstring(raddr,addr,sizeof(addr)))
+ ABORT(r);
+ if(r=nr_transport_addr_get_port(raddr,&port))
+ ABORT(r);
+ snprintf(attr,maxlen," raddr %s rport %d",addr,port);
+ break;
+ case RELAYED:
+ // comes from XorMappedAddress via AllocateResponse
+ if(r=nr_transport_addr_get_addrstring(raddr,addr,sizeof(addr)))
+ ABORT(r);
+ if(r=nr_transport_addr_get_port(raddr,&port))
+ ABORT(r);
+
+ snprintf(attr,maxlen," raddr %s rport %d",addr,port);
+ break;
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ if (cand->base.protocol==IPPROTO_TCP && cand->tcp_type){
+ len=strlen(attr);
+ attr+=len;
+ maxlen-=len;
+ snprintf(attr,maxlen," tcptype %s",nr_tcp_type_name(cand->tcp_type));
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h
new file mode 100644
index 000000000..16be40276
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_candidate_h
+#define _ice_candidate_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED, CTYPE_MAX} nr_ice_candidate_type;
+
+struct nr_ice_candidate_ {
+ char *label;
+ char codeword[5];
+ int state;
+#define NR_ICE_CAND_STATE_CREATED 1
+#define NR_ICE_CAND_STATE_INITIALIZING 2
+#define NR_ICE_CAND_STATE_INITIALIZED 3
+#define NR_ICE_CAND_STATE_FAILED 4
+#define NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED 9
+#define NR_ICE_CAND_PEER_CANDIDATE_PAIRED 10
+ struct nr_ice_ctx_ *ctx;
+ nr_ice_socket *isock; /* The socket to read from
+ (it contains all other candidates
+ on this socket) */
+ nr_socket *osock; /* The socket to write to */
+ nr_ice_media_stream *stream; /* The media stream this is associated with */
+ nr_ice_component *component; /* The component this is associated with */
+ nr_ice_candidate_type type; /* The type of the candidate (S 4.1.1) */
+ nr_socket_tcp_type tcp_type;
+ UCHAR component_id; /* The component id (S 4.1.2.1) */
+ nr_transport_addr addr; /* The advertised address;
+ JDR calls this the candidate */
+ nr_transport_addr base; /* The base address (S 2.1)*/
+ char *foundation; /* Foundation for the candidate (S 4) */
+ UINT4 priority; /* The priority value (S 5.4 */
+ nr_ice_stun_server *stun_server;
+ nr_transport_addr stun_server_addr; /* Resolved STUN server address */
+ void *delay_timer;
+ void *resolver_handle;
+
+ /* Holding data for STUN and TURN */
+ union {
+ struct {
+ nr_stun_client_ctx *stun;
+ void *stun_handle;
+ /* If this is a srflx that is piggybacking on a relay candidate, this is
+ * a back pointer to that relay candidate. */
+ nr_ice_candidate *relay_candidate;
+ } srvrflx;
+ struct {
+ nr_turn_client_ctx *turn;
+ nr_ice_turn_server *server;
+ nr_ice_candidate *srvflx_candidate;
+ nr_socket *turn_sock;
+ void *turn_handle;
+ } relayed;
+ } u;
+
+ NR_async_cb done_cb;
+ void *cb_arg;
+
+ NR_async_cb ready_cb;
+ void *ready_cb_arg;
+ void *ready_cb_timer;
+
+ TAILQ_ENTRY(nr_ice_candidate_) entry_sock;
+ TAILQ_ENTRY(nr_ice_candidate_) entry_comp;
+};
+
+extern char *nr_ice_candidate_type_names[];
+extern char *nr_ice_candidate_tcp_type_names[];
+
+
+int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_socket_tcp_type tcp_type, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp);
+int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
+void nr_ice_candidate_compute_codeword(nr_ice_candidate *cand);
+int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr);
+int nr_ice_candidate_destroy(nr_ice_candidate **candp);
+int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen);
+int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp);
+int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp);
+int nr_ice_candidate_compute_priority(nr_ice_candidate *cand);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c
new file mode 100644
index 000000000..6c07ae2a6
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c
@@ -0,0 +1,684 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_candidate_pair.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <assert.h>
+#include <string.h>
+#include <nr_api.h>
+#include "async_timer.h"
+#include "ice_ctx.h"
+#include "ice_util.h"
+#include "ice_codeword.h"
+#include "stun.h"
+
+static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
+
+static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg);
+static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
+ nr_ice_candidate *lcand, nr_ice_candidate *rcand);
+
+static void nr_ice_candidate_pair_set_priority(nr_ice_cand_pair *pair)
+ {
+ /* Priority computation S 5.7.2 */
+ UINT8 controlling_priority, controlled_priority;
+ if(pair->pctx->controlling)
+ {
+ controlling_priority=pair->local->priority;
+ controlled_priority=pair->remote->priority;
+ }
+ else{
+ controlling_priority=pair->remote->priority;
+ controlled_priority=pair->local->priority;
+ }
+ pair->priority=(MIN(controlling_priority, controlled_priority))<<32 |
+ (MAX(controlling_priority, controlled_priority))<<1 |
+ (controlled_priority > controlling_priority?0:1);
+ }
+
+int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
+ {
+ nr_ice_cand_pair *pair=0;
+ int r,_status;
+ UINT4 RTO;
+ nr_ice_candidate tmpcand;
+ UINT8 t_priority;
+
+ if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
+ ABORT(R_NO_MEMORY);
+
+ pair->pctx=pctx;
+
+ nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
+
+ if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
+ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL))
+ ABORT(r);
+
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
+ pair->local=lcand;
+ pair->remote=rcand;
+
+ nr_ice_candidate_pair_set_priority(pair);
+
+ /*
+ TODO(bcampen@mozilla.com): Would be nice to log why this candidate was
+ created (initial pair generation, triggered check, and new trickle
+ candidate seem to be the possibilities here).
+ */
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s)/CAND-PAIR(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx)",pctx->ctx->label,pair->codeword,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority);
+
+ /* Foundation */
+ if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
+ rcand->foundation,NULL))
+ ABORT(r);
+
+ /* Compute the RTO per S 16 */
+ RTO = MAX(100, (pctx->ctx->Ta * pctx->waiting_pairs));
+
+ /* Make a bogus candidate to compute a theoretical peer reflexive
+ * priority per S 7.1.1.1 */
+ memcpy(&tmpcand, lcand, sizeof(tmpcand));
+ tmpcand.type = PEER_REFLEXIVE;
+ if (r=nr_ice_candidate_compute_priority(&tmpcand))
+ ABORT(r);
+ t_priority = tmpcand.priority;
+
+ /* Our sending context */
+ if(r=nr_stun_client_ctx_create(pair->as_string,
+ lcand->osock,
+ &rcand->addr,RTO,&pair->stun_client))
+ ABORT(r);
+ if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(rcand->stream->l2r_user)))
+ ABORT(R_NO_MEMORY);
+ if(r=r_data_copy(&pair->stun_client->params.ice_binding_request.password,
+ &rcand->stream->l2r_pass))
+ ABORT(r);
+ /* TODO(ekr@rtfm.com): Do we need to frob this when we change role. Bug 890667 */
+ pair->stun_client->params.ice_binding_request.control = pctx->controlling?
+ NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
+ pair->stun_client->params.ice_binding_request.priority=t_priority;
+
+ pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
+
+ *pairp=pair;
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_ice_candidate_pair_destroy(&pair);
+ }
+ return(_status);
+ }
+
+int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp)
+ {
+ nr_ice_cand_pair *pair;
+
+ if(!pairp || !*pairp)
+ return(0);
+
+ pair=*pairp;
+ *pairp=0;
+
+ RFREE(pair->as_string);
+ RFREE(pair->foundation);
+ nr_ice_socket_deregister(pair->local->isock,pair->stun_client_handle);
+ if (pair->stun_client) {
+ RFREE(pair->stun_client->params.ice_binding_request.username);
+ RFREE(pair->stun_client->params.ice_binding_request.password.data);
+ nr_stun_client_ctx_destroy(&pair->stun_client);
+ }
+
+ NR_async_timer_cancel(pair->stun_cb_timer);
+ NR_async_timer_cancel(pair->restart_role_change_cb_timer);
+ NR_async_timer_cancel(pair->restart_nominated_cb_timer);
+
+ RFREE(pair);
+ return(0);
+ }
+
+int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
+ {
+ assert(pair->state==NR_ICE_PAIR_STATE_FROZEN);
+
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
+
+ return(0);
+ }
+
+static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_cand_pair *pair=cb_arg;
+ nr_ice_cand_pair *actual_pair=0;
+ nr_ice_candidate *cand=0;
+ nr_stun_message *sres;
+ nr_transport_addr *request_src;
+ nr_transport_addr *request_dst;
+ nr_transport_addr *response_src;
+ nr_transport_addr response_dst;
+ nr_stun_message_attribute *attr;
+
+ pair->stun_cb_timer=0;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s): STUN cb on pair addr = %s",
+ pair->pctx->label,pair->local->stream->label,pair->codeword,pair->as_string);
+
+ /* This ordinarily shouldn't happen, but can if we're
+ doing the second check to confirm nomination.
+ Just bail out */
+ if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED)
+ goto done;
+
+ switch(pair->stun_client->state){
+ case NR_STUN_CLIENT_STATE_FAILED:
+ sres=pair->stun_client->response;
+ if(sres && nr_stun_message_has_attribute(sres,NR_STUN_ATTR_ERROR_CODE,&attr)&&attr->u.error_code.number==487){
+
+ /*
+ * Flip the controlling bit; subsequent 487s for other pairs will be
+ * ignored, since we abandon their STUN transactions.
+ */
+ nr_ice_peer_ctx_switch_controlling_role(pair->pctx);
+
+ return;
+ }
+ /* Fall through */
+ case NR_STUN_CLIENT_STATE_TIMED_OUT:
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
+ break;
+ case NR_STUN_CLIENT_STATE_DONE:
+ /* make sure the addresses match up S 7.1.2.2 */
+ response_src=&pair->stun_client->peer_addr;
+ request_dst=&pair->remote->addr;
+ if (nr_transport_addr_cmp(response_src,request_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND-PAIR(%s): Peer address mismatch %s != %s",pair->pctx->label,pair->codeword,response_src->as_string,request_dst->as_string);
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
+ break;
+ }
+ request_src=&pair->stun_client->my_addr;
+ nr_socket_getaddr(pair->local->osock,&response_dst);
+ if (nr_transport_addr_cmp(request_src,&response_dst,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND-PAIR(%s): Local address mismatch %s != %s",pair->pctx->label,pair->codeword,request_src->as_string,response_dst.as_string);
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
+ break;
+ }
+
+ if(strlen(pair->stun_client->results.ice_binding_response.mapped_addr.as_string)==0){
+ /* we're using the mapped_addr returned by the server to lookup our
+ * candidate, but if the server fails to do that we can't perform
+ * the lookup -- this may be a BUG because if we've gotten here
+ * then the transaction ID check succeeded, and perhaps we should
+ * just assume that it's the server we're talking to and that our
+ * peer is ok, but I'm not sure how that'll interact with the
+ * peer reflexive logic below */
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND-PAIR(%s): server failed to return mapped address on pair %s", pair->pctx->label,pair->codeword,pair->as_string);
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
+ break;
+ }
+ else if(!nr_transport_addr_cmp(&pair->local->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_SUCCEEDED);
+ }
+ else if(pair->stun_client->state == NR_STUN_CLIENT_STATE_DONE) {
+ /* OK, this didn't correspond to a pair on the check list, but
+ it probably matches one of our candidates */
+
+ cand=TAILQ_FIRST(&pair->local->component->candidates);
+ while(cand){
+ if(!nr_transport_addr_cmp(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): found pre-existing local candidate of type %d for mapped address %s", pair->pctx->label,cand->type,cand->addr.as_string);
+ assert(cand->type != HOST);
+ break;
+ }
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ if(!cand) {
+ /* OK, nothing found, must be a new peer reflexive */
+ if (pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) {
+ /* Any STUN response with a reflexive address in it is unwanted
+ when we'll send on relay only. Bail since cand is used below. */
+ goto done;
+ }
+ if(r=nr_ice_candidate_create(pair->pctx->ctx,
+ pair->local->component,pair->local->isock,pair->local->osock,
+ PEER_REFLEXIVE,pair->local->tcp_type,0,pair->local->component->component_id,&cand))
+ ABORT(r);
+ if(r=nr_transport_addr_copy(&cand->addr,&pair->stun_client->results.ice_binding_response.mapped_addr))
+ ABORT(r);
+ cand->state=NR_ICE_CAND_STATE_INITIALIZED;
+ TAILQ_INSERT_TAIL(&pair->local->component->candidates,cand,entry_comp);
+ } else {
+ /* Check if we have a pair for this candidate already. */
+ if(r=nr_ice_media_stream_find_pair(pair->remote->stream, cand, pair->remote, &actual_pair)) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): no pair exists for %s and %s", pair->pctx->label,cand->addr.as_string, pair->remote->addr.as_string);
+ }
+ }
+
+ if(!actual_pair) {
+ if(r=nr_ice_candidate_pair_create(pair->pctx,cand,pair->remote, &actual_pair))
+ ABORT(r);
+
+ if(r=nr_ice_component_insert_pair(actual_pair->remote->component,actual_pair))
+ ABORT(r);
+
+ /* If the original pair was nominated, make us nominated too. */
+ if(pair->peer_nominated)
+ actual_pair->peer_nominated=1;
+
+ /* Now mark the orig pair failed */
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FAILED);
+ }
+
+ assert(actual_pair);
+ nr_ice_candidate_pair_set_state(actual_pair->pctx,actual_pair,NR_ICE_PAIR_STATE_SUCCEEDED);
+ pair=actual_pair;
+
+ }
+
+ /* Should we set nominated? */
+ if(pair->pctx->controlling){
+ if(pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION)
+ pair->nominated=1;
+ }
+ else{
+ if(pair->peer_nominated)
+ pair->nominated=1;
+ }
+
+
+ /* increment the number of valid pairs in the component */
+ /* We don't bother to maintain a separate valid list */
+ pair->remote->component->valid_pairs++;
+
+ /* S 7.1.2.2: unfreeze other pairs with the same foundation*/
+ if(r=nr_ice_media_stream_unfreeze_pairs_foundation(pair->remote->stream,pair->foundation))
+ ABORT(r);
+
+ /* Deal with this pair being nominated */
+ if(pair->nominated){
+ if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
+ ABORT(r);
+ }
+
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ /* If we're controlling but in regular mode, ask the handler
+ if he wants to nominate something and stop... */
+ if(pair->pctx->controlling && !(pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION)){
+
+ if(r=nr_ice_component_select_pair(pair->pctx,pair->remote->component)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+ }
+
+ done:
+ _status=0;
+ abort:
+ return;
+ }
+
+static void nr_ice_candidate_pair_restart(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+ UINT4 mode;
+
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_IN_PROGRESS);
+
+ /* Start STUN */
+ if(pair->pctx->controlling && (pair->pctx->ctx->flags & NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION))
+ mode=NR_ICE_CLIENT_MODE_USE_CANDIDATE;
+ else
+ mode=NR_ICE_CLIENT_MODE_BINDING_REQUEST;
+
+ nr_stun_client_reset(pair->stun_client);
+
+ if(r=nr_stun_client_start(pair->stun_client,mode,nr_ice_candidate_pair_stun_cb,pair))
+ ABORT(r);
+
+ if ((r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))) {
+ /* ignore if this fails (which it shouldn't) because it's only an
+ * optimization and the cleanup routines are not going to do the right
+ * thing if this fails */
+ assert(0);
+ }
+
+ _status=0;
+ abort:
+ if(_status){
+ /* Don't fire the CB, but schedule it to fire ASAP */
+ assert(!pair->stun_cb_timer);
+ NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_stun_cb,pair, &pair->stun_cb_timer);
+ _status=0;
+ }
+ }
+
+int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+
+ /* Register the stun ctx for when responses come in*/
+ if(r=nr_ice_socket_register_stun_client(pair->local->isock,pair->stun_client,&pair->stun_client_handle))
+ ABORT(r);
+
+ nr_ice_candidate_pair_restart(pctx, pair);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_candidate_copy_for_triggered_check(nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+ nr_ice_cand_pair *copy;
+
+ if(r=nr_ice_candidate_pair_create(pair->pctx, pair->local, pair->remote, &copy))
+ ABORT(r);
+
+ /* Preserve nomination status */
+ copy->peer_nominated= pair->peer_nominated;
+ copy->nominated = pair->nominated;
+
+ r_log(LOG_ICE,LOG_INFO,"CAND-PAIR(%s): Adding pair to check list and trigger check queue: %s",pair->codeword,pair->as_string);
+ if(r=nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,copy))
+ ABORT(r);
+ nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,copy);
+
+ copy->triggered = 1;
+ nr_ice_candidate_pair_set_state(copy->pctx,copy,NR_ICE_PAIR_STATE_WAITING);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+
+ if(pair->state==NR_ICE_PAIR_STATE_CANCELLED) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): Ignoring matching but canceled pair",pctx->label,pair->codeword);
+ return(0);
+ } else if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): No new trigger check for succeeded pair",pctx->label,pair->codeword);
+ return(0);
+ }
+
+ /* Do not run this logic more than once on a given pair */
+ if(!pair->triggered){
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): triggered check on %s",pctx->label,pair->codeword,pair->as_string);
+
+ pair->triggered=1;
+
+ switch(pair->state){
+ case NR_ICE_PAIR_STATE_FAILED:
+ /* OK, there was a pair, it's just invalid: According to Section
+ * 7.2.1.4, we need to resurrect it */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): received STUN check on failed pair, resurrecting: %s",pctx->label,pair->codeword,pair->as_string);
+ /* fall through */
+ case NR_ICE_PAIR_STATE_FROZEN:
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
+ /* fall through even further */
+ case NR_ICE_PAIR_STATE_WAITING:
+ /* Append it additionally to the trigger check queue */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): Inserting pair to trigger check queue: %s",pctx->label,pair->codeword,pair->as_string);
+ nr_ice_candidate_pair_trigger_check_append(&pair->remote->stream->trigger_check_queue,pair);
+ break;
+ case NR_ICE_PAIR_STATE_IN_PROGRESS:
+ /* Instead of trying to maintain two stun contexts on the same pair,
+ * and handling heterogenous responses and error conditions, we instead
+ * create a second pair that is identical except that it has the
+ * |triggered| bit set. We also cancel the original pair, but it can
+ * still succeed on its own in the special waiting state. */
+ if(r=nr_ice_candidate_copy_for_triggered_check(pair))
+ ABORT(r);
+ nr_ice_candidate_pair_cancel(pair->pctx,pair,1);
+ break;
+ default:
+ /* all states are handled - a new/unknown state should not
+ * automatically enter the start_checks() below */
+ assert(0);
+ break;
+ }
+
+ /* Ensure that the timers are running to start checks on the topmost entry
+ * of the triggered check queue. */
+ if(r=nr_ice_media_stream_start_checks(pair->pctx,pair->remote->stream))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state)
+ {
+ if(pair->state != NR_ICE_PAIR_STATE_FAILED){
+ /* If it's already running we need to terminate the stun */
+ if(pair->state==NR_ICE_PAIR_STATE_IN_PROGRESS){
+ if(move_to_wait_state) {
+ nr_stun_client_wait(pair->stun_client);
+ } else {
+ nr_stun_client_cancel(pair->stun_client);
+ }
+ }
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_CANCELLED);
+ }
+
+ return(0);
+ }
+
+int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+
+ if(!pair){
+ r_log(LOG_ICE,LOG_ERR,"ICE-PAIR: No pair chosen");
+ ABORT(R_BAD_ARGS);
+ }
+
+ if(pair->state!=NR_ICE_PAIR_STATE_SUCCEEDED){
+ r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s)/CAND-PAIR(%s): tried to install non-succeeded pair, ignoring: %s",pair->pctx->label,pair->codeword,pair->as_string);
+ }
+ else{
+ /* Ok, they chose one */
+ /* 1. Send a new request with nominated. Do it as a scheduled
+ event to avoid reentrancy issues. Only do this if it hasn't
+ happened already (though this shouldn't happen.)
+ */
+ if(!pair->restart_nominated_cb_timer)
+ NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_restart_stun_nominated_cb,pair,&pair->restart_nominated_cb_timer);
+
+ /* 2. Tell ourselves this pair is ready */
+ if(r=nr_ice_component_nominated_pair(pair->remote->component, pair))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
+ {
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): setting pair to state %s: %s",
+ pctx->label,pair->codeword,nr_ice_cand_pair_states[state],pair->as_string);
+
+ /* NOTE: This function used to reference pctx->state instead of
+ pair->state and the assignment to pair->state was at the top
+ of this function. Because pctx->state was never changed, this seems to have
+ been a typo. The natural logic is "if the state changed
+ decrement the counter" so this implies we should be checking
+ the pair state rather than the pctx->state.
+
+ This didn't cause big problems because waiting_pairs was only
+ used for pacing, so the pacing just was kind of broken.
+
+ This note is here as a reminder until we do more testing
+ and make sure that in fact this was a typo.
+ */
+ if(pair->state!=NR_ICE_PAIR_STATE_WAITING){
+ if(state==NR_ICE_PAIR_STATE_WAITING)
+ pctx->waiting_pairs++;
+ }
+ else{
+ if(state!=NR_ICE_PAIR_STATE_WAITING)
+ pctx->waiting_pairs--;
+
+ assert(pctx->waiting_pairs>=0);
+ }
+ pair->state=state;
+
+
+ if(pair->state==NR_ICE_PAIR_STATE_FAILED ||
+ pair->state==NR_ICE_PAIR_STATE_CANCELLED){
+ if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out)
+ {
+ /*r_log(LOG_ICE,LOG_DEBUG,"CAND-PAIR(%s): pair %s: state=%s, priority=0x%llx\n",pair->codeword,pair->as_string,nr_ice_cand_pair_states[pair->state],pair->priority);*/
+
+ return(0);
+ }
+
+
+int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
+ {
+ if(pair->triggered_check_queue_entry.tqe_next ||
+ pair->triggered_check_queue_entry.tqe_prev)
+ return(0);
+
+ TAILQ_INSERT_TAIL(head,pair,triggered_check_queue_entry);
+
+ return(0);
+ }
+
+int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair)
+ {
+ nr_ice_cand_pair *c1;
+
+ c1=TAILQ_FIRST(head);
+ while(c1){
+ if(c1->priority < pair->priority){
+ TAILQ_INSERT_BEFORE(c1,pair,check_queue_entry);
+ break;
+ }
+
+ c1=TAILQ_NEXT(c1,check_queue_entry);
+ }
+ if(!c1) TAILQ_INSERT_TAIL(head,pair,check_queue_entry);
+
+ return(0);
+ }
+
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_cand_pair *pair=cb_arg;
+ int r,_status;
+
+ pair->restart_nominated_cb_timer=0;
+
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s)/COMP(%d): Restarting pair as nominated: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->as_string);
+
+ nr_stun_client_reset(pair->stun_client);
+
+ if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
+ ABORT(r);
+
+ if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return;
+ }
+
+static void nr_ice_candidate_pair_restart_stun_role_change_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_cand_pair *pair=cb_arg;
+
+ pair->restart_role_change_cb_timer=0;
+
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/CAND-PAIR(%s):COMP(%d): Restarting pair as %s: %s",pair->pctx->label,pair->local->stream->label,pair->codeword,pair->remote->component->component_id,pair->pctx->controlling ? "CONTROLLING" : "CONTROLLED",pair->as_string);
+
+ nr_ice_candidate_pair_restart(pair->pctx, pair);
+ }
+
+void nr_ice_candidate_pair_role_change(nr_ice_cand_pair *pair)
+ {
+ pair->stun_client->params.ice_binding_request.control = pair->pctx->controlling ? NR_ICE_CONTROLLING : NR_ICE_CONTROLLED;
+ nr_ice_candidate_pair_set_priority(pair);
+
+ if(pair->state == NR_ICE_PAIR_STATE_IN_PROGRESS) {
+ /* We could try only restarting in-progress pairs when they receive their
+ * 487, but this ends up being simpler, because any extra 487 are dropped.
+ */
+ if(!pair->restart_role_change_cb_timer)
+ NR_ASYNC_TIMER_SET(0,nr_ice_candidate_pair_restart_stun_role_change_cb,pair,&pair->restart_role_change_cb_timer);
+ }
+ }
+
+static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
+ nr_ice_candidate *lcand, nr_ice_candidate *rcand)
+ {
+ char as_string[2048];
+
+ snprintf(as_string,
+ sizeof(as_string),
+ "%s|%s(%s|%s)",
+ lcand->addr.as_string,
+ rcand->addr.as_string,
+ lcand->label,
+ rcand->label);
+
+ nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h
new file mode 100644
index 000000000..171ded4a0
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h
@@ -0,0 +1,95 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_candidate_pair_h
+#define _ice_candidate_pair_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+
+struct nr_ice_cand_pair_ {
+ nr_ice_peer_ctx *pctx;
+ char codeword[5];
+ char *as_string;
+ int state; /* The current state (S 5.7.3) */
+#define NR_ICE_PAIR_STATE_FROZEN 1
+#define NR_ICE_PAIR_STATE_WAITING 2
+#define NR_ICE_PAIR_STATE_IN_PROGRESS 3
+#define NR_ICE_PAIR_STATE_FAILED 4
+#define NR_ICE_PAIR_STATE_SUCCEEDED 5
+#define NR_ICE_PAIR_STATE_CANCELLED 6
+
+ UCHAR peer_nominated; /* The peer sent USE-CANDIDATE
+ on this check */
+ UCHAR nominated; /* Is this nominated or not */
+
+ UCHAR triggered; /* Ignore further trigger check requests */
+
+ UINT8 priority; /* The priority for this pair */
+ nr_ice_candidate *local; /* The local candidate */
+ nr_ice_candidate *remote; /* The remote candidate */
+ char *foundation; /* The combined foundations */
+
+ nr_stun_client_ctx *stun_client; /* STUN context when acting as a client */
+ void *stun_client_handle;
+
+ void *stun_cb_timer;
+ void *restart_role_change_cb_timer;
+ void *restart_nominated_cb_timer;
+
+ TAILQ_ENTRY(nr_ice_cand_pair_) check_queue_entry; /* the check list */
+ TAILQ_ENTRY(nr_ice_cand_pair_) triggered_check_queue_entry; /* the trigger check queue */
+};
+
+int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
+int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
+int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
+int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state);
+int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
+int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
+int nr_ice_candidate_pair_trigger_check_append(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
+void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
+int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
+void nr_ice_candidate_pair_role_change(nr_ice_cand_pair *pair);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_codeword.h b/media/mtransport/third_party/nICEr/src/ice/ice_codeword.h
new file mode 100644
index 000000000..76fce0b69
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_codeword.h
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_codeword_h
+#define _ice_codeword_h
+
+void nr_ice_compute_codeword(char *buf, int len,char *codeword);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.c b/media/mtransport/third_party/nICEr/src/ice/ice_component.c
new file mode 100644
index 000000000..2be25efca
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c
@@ -0,0 +1,1688 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_component.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <string.h>
+#include <assert.h>
+#include <nr_api.h>
+#include <registry.h>
+#include <async_timer.h>
+#include "ice_ctx.h"
+#include "ice_codeword.h"
+#include "stun.h"
+#include "nr_socket_local.h"
+#include "nr_socket_turn.h"
+#include "nr_socket_wrapper.h"
+#include "nr_socket_buffered_stun.h"
+#include "nr_socket_multi_tcp.h"
+#include "ice_reg.h"
+#include "nr_crypto.h"
+#include "r_time.h"
+
+static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error);
+static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp);
+void nr_ice_component_consent_schedule_consent_timer(nr_ice_component *comp);
+void nr_ice_component_consent_destroy(nr_ice_component *comp);
+
+/* This function takes ownership of the contents of req (but not req itself) */
+static int nr_ice_pre_answer_request_create(nr_transport_addr *dst, nr_stun_server_request *req, nr_ice_pre_answer_request **parp)
+ {
+ int r, _status;
+ nr_ice_pre_answer_request *par = 0;
+ nr_stun_message_attribute *attr;
+
+ if (!(par = RCALLOC(sizeof(nr_ice_pre_answer_request))))
+ ABORT(R_NO_MEMORY);
+
+ par->req = *req; /* Struct assignment */
+ memset(req, 0, sizeof(*req)); /* Zero contents to avoid confusion */
+
+ if (r=nr_transport_addr_copy(&par->local_addr, dst))
+ ABORT(r);
+ if (!nr_stun_message_has_attribute(par->req.request, NR_STUN_ATTR_USERNAME, &attr))
+ ABORT(R_INTERNAL);
+ if (!(par->username = r_strdup(attr->u.username)))
+ ABORT(R_NO_MEMORY);
+
+ *parp=par;
+ _status=0;
+ abort:
+ if (_status) {
+ /* Erase the request so we don't free it */
+ memset(&par->req, 0, sizeof(nr_stun_server_request));
+ nr_ice_pre_answer_request_destroy(&par);
+ }
+
+ return(_status);
+ }
+
+static int nr_ice_pre_answer_request_destroy(nr_ice_pre_answer_request **parp)
+ {
+ nr_ice_pre_answer_request *par;
+
+ if (!parp || !*parp)
+ return(0);
+
+ par = *parp;
+ *parp = 0;
+
+ nr_stun_message_destroy(&par->req.request);
+ nr_stun_message_destroy(&par->req.response);
+
+ RFREE(par->username);
+ RFREE(par);
+
+ return(0);
+ }
+
+int nr_ice_component_create(nr_ice_media_stream *stream, int component_id, nr_ice_component **componentp)
+ {
+ int _status;
+ nr_ice_component *comp=0;
+
+ if(!(comp=RCALLOC(sizeof(nr_ice_component))))
+ ABORT(R_NO_MEMORY);
+
+ comp->state=NR_ICE_COMPONENT_UNPAIRED;
+ comp->component_id=component_id;
+ comp->stream=stream;
+ comp->ctx=stream->ctx;
+
+ STAILQ_INIT(&comp->sockets);
+ TAILQ_INIT(&comp->candidates);
+ STAILQ_INIT(&comp->pre_answer_reqs);
+
+ STAILQ_INSERT_TAIL(&stream->components,comp,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_component_destroy(nr_ice_component **componentp)
+ {
+ nr_ice_component *component;
+ nr_ice_socket *s1,*s2;
+ nr_ice_candidate *c1,*c2;
+ nr_ice_pre_answer_request *r1,*r2;
+
+ if(!componentp || !*componentp)
+ return(0);
+
+ component=*componentp;
+ *componentp=0;
+
+ nr_ice_component_consent_destroy(component);
+
+ /* Detach ourselves from the sockets */
+ if (component->local_component){
+ nr_ice_socket *isock=STAILQ_FIRST(&component->local_component->sockets);
+ while(isock){
+ nr_stun_server_remove_client(isock->stun_server, component);
+ isock=STAILQ_NEXT(isock, entry);
+ }
+ }
+
+ /* candidates MUST be destroyed before the sockets so that
+ they can deregister */
+ TAILQ_FOREACH_SAFE(c1, &component->candidates, entry_comp, c2){
+ TAILQ_REMOVE(&component->candidates,c1,entry_comp);
+ nr_ice_candidate_destroy(&c1);
+ }
+
+ STAILQ_FOREACH_SAFE(s1, &component->sockets, entry, s2){
+ STAILQ_REMOVE(&component->sockets,s1,nr_ice_socket_,entry);
+ nr_ice_socket_destroy(&s1);
+ }
+
+ STAILQ_FOREACH_SAFE(r1, &component->pre_answer_reqs, entry, r2){
+ STAILQ_REMOVE(&component->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry);
+ nr_ice_pre_answer_request_destroy(&r1);
+ }
+
+ RFREE(component);
+ return(0);
+ }
+
+static int nr_ice_component_create_stun_server_ctx(nr_ice_component *component, nr_ice_socket *isock, nr_socket *sock, nr_transport_addr *addr, char *lufrag, Data *pwd)
+ {
+ char label[256];
+ int r,_status;
+
+ /* Create a STUN server context for this socket */
+ snprintf(label, sizeof(label), "server(%s)", addr->as_string);
+ if(r=nr_stun_server_ctx_create(label,sock,&isock->stun_server))
+ ABORT(r);
+ if(r=nr_ice_socket_register_stun_server(isock,isock->stun_server,&isock->stun_server_handle))
+ ABORT(r);
+
+ /* Add the default STUN credentials so that we can respond before
+ we hear about the peer.*/
+ if(r=nr_stun_server_add_default_client(isock->stun_server, lufrag, pwd, nr_ice_component_stun_server_default_cb, component))
+ ABORT(r);
+
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_local_addr *addrs, int addr_ct, char *lufrag, Data *pwd)
+ {
+ nr_socket *sock;
+ nr_ice_socket *isock=0;
+ nr_ice_candidate *cand=0;
+ int i;
+ int j;
+ int r,_status;
+
+ if(ctx->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY) {
+ /* No UDP support if we must use a proxy */
+ return 0;
+ }
+
+ /* Now one ice_socket for each address */
+ for(i=0;i<addr_ct;i++){
+ char suppress;
+
+ if(r=NR_reg_get2_char(NR_ICE_REG_SUPPRESS_INTERFACE_PRFX,addrs[i].addr.ifname,&suppress)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+ else{
+ if(suppress)
+ continue;
+ }
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): host address %s",ctx->label,addrs[i].addr.as_string);
+ if((r=nr_socket_factory_create_socket(ctx->socket_factory,&addrs[i].addr,&sock))){
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): couldn't create socket for address %s",ctx->label,addrs[i].addr.as_string);
+ continue;
+ }
+
+ if(r=nr_ice_socket_create(ctx,component,sock,NR_ICE_SOCKET_TYPE_DGRAM,&isock))
+ ABORT(r);
+
+ if (!(ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY)) {
+ /* Create one host candidate */
+ if(r=nr_ice_candidate_create(ctx,component,isock,sock,HOST,0,0,
+ component->component_id,&cand))
+ ABORT(r);
+
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+
+ /* And a srvrflx candidate for each STUN server */
+ for(j=0;j<ctx->stun_server_ct;j++){
+ /* Skip non-UDP */
+ if(ctx->stun_servers[j].transport!=IPPROTO_UDP)
+ continue;
+
+ /* Ensure id is set (nr_ice_ctx_set_stun_servers does not) */
+ ctx->stun_servers[j].id = j;
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock,sock,SERVER_REFLEXIVE,0,
+ &ctx->stun_servers[j],component->component_id,&cand))
+ ABORT(r);
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+ }
+ }
+ else{
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): relay only option results in no host candidate for %s",ctx->label,addrs[i].addr.as_string);
+ }
+
+#ifdef USE_TURN
+ if ((ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) &&
+ (ctx->turn_server_ct == 0)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): relay only option is set without any TURN server configured",ctx->label);
+ }
+ /* And both a srvrflx and relayed candidate for each TURN server (unless
+ we're in relay-only mode, in which case just the relayed one) */
+ for(j=0;j<ctx->turn_server_ct;j++){
+ nr_socket *turn_sock;
+ nr_ice_candidate *srvflx_cand=0;
+
+ /* Skip non-UDP */
+ if (ctx->turn_servers[j].turn_server.transport != IPPROTO_UDP)
+ continue;
+
+ if (!(ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY)) {
+ /* Ensure id is set with a unique value */
+ ctx->turn_servers[j].turn_server.id = j + ctx->stun_server_ct;
+ /* srvrflx */
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock,sock,SERVER_REFLEXIVE,0,
+ &ctx->turn_servers[j].turn_server,component->component_id,&cand))
+ ABORT(r);
+ cand->state=NR_ICE_CAND_STATE_INITIALIZING; /* Don't start */
+ cand->done_cb=nr_ice_gather_finished_cb;
+ cand->cb_arg=cand;
+
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ srvflx_cand=cand;
+ cand=0;
+ }
+ /* relayed*/
+ if(r=nr_socket_turn_create(sock, &turn_sock))
+ ABORT(r);
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock,turn_sock,RELAYED,0,
+ &ctx->turn_servers[j].turn_server,component->component_id,&cand))
+ ABORT(r);
+ if (srvflx_cand) {
+ cand->u.relayed.srvflx_candidate=srvflx_cand;
+ srvflx_cand->u.srvrflx.relay_candidate=cand;
+ }
+ cand->u.relayed.server=&ctx->turn_servers[j];
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+
+ cand=0;
+ }
+#endif /* USE_TURN */
+
+ /* Create a STUN server context for this socket */
+ if ((r=nr_ice_component_create_stun_server_ctx(component,isock,sock,&addrs[i].addr,lufrag,pwd)))
+ ABORT(r);
+
+ STAILQ_INSERT_TAIL(&component->sockets,isock,entry);
+ }
+
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_component_get_port_from_ephemeral_range(uint16_t *port)
+ {
+ int _status, r;
+ void *buf = port;
+ if(r=nr_crypto_random_bytes(buf, 2))
+ ABORT(r);
+ *port|=49152; /* make it fit into IANA ephemeral port range >= 49152 */
+ _status=0;
+abort:
+ return(_status);
+ }
+
+static int nr_ice_component_create_tcp_host_candidate(struct nr_ice_ctx_ *ctx,
+ nr_ice_component *component, nr_transport_addr *interface_addr, nr_socket_tcp_type tcp_type,
+ int backlog, int so_sock_ct, char *lufrag, Data *pwd, nr_ice_socket **isock)
+ {
+ int r,_status;
+ nr_ice_candidate *cand=0;
+ int tries=3;
+ nr_ice_socket *isock_tmp=0;
+ nr_socket *nrsock=0;
+ nr_transport_addr addr;
+ uint16_t local_port;
+
+ if ((r=nr_transport_addr_copy(&addr,interface_addr)))
+ ABORT(r);
+ addr.protocol=IPPROTO_TCP;
+
+ do{
+ if (!tries--)
+ ABORT(r);
+
+ if((r=nr_ice_component_get_port_from_ephemeral_range(&local_port)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_set_port(&addr, local_port)))
+ ABORT(r);
+
+ if((r=nr_transport_addr_fmt_addr_string(&addr)))
+ ABORT(r);
+
+ /* It would be better to stop trying if there is error other than
+ port already used, but it'd require significant work to support this. */
+ r=nr_socket_multi_tcp_create(ctx,&addr,tcp_type,so_sock_ct,NR_STUN_MAX_MESSAGE_SIZE,&nrsock);
+
+ } while(r);
+
+ if((tcp_type == TCP_TYPE_PASSIVE) && (r=nr_socket_listen(nrsock,backlog)))
+ ABORT(r);
+
+ if((r=nr_ice_socket_create(ctx,component,nrsock,NR_ICE_SOCKET_TYPE_STREAM_TCP,&isock_tmp)))
+ ABORT(r);
+
+ /* nr_ice_socket took ownership of nrsock */
+ nrsock=NULL;
+
+ /* Create a STUN server context for this socket */
+ if ((r=nr_ice_component_create_stun_server_ctx(component,isock_tmp,isock_tmp->sock,&addr,lufrag,pwd)))
+ ABORT(r);
+
+ if((r=nr_ice_candidate_create(ctx,component,isock_tmp,isock_tmp->sock,HOST,tcp_type,0,
+ component->component_id,&cand)))
+ ABORT(r);
+
+ if (isock)
+ *isock=isock_tmp;
+
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+
+ STAILQ_INSERT_TAIL(&component->sockets,isock_tmp,entry);
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_ice_socket_destroy(&isock_tmp);
+ nr_socket_destroy(&nrsock);
+ }
+ return(_status);
+ }
+
+static int nr_ice_component_initialize_tcp(struct nr_ice_ctx_ *ctx,nr_ice_component *component, nr_local_addr *addrs, int addr_ct, char *lufrag, Data *pwd)
+ {
+ nr_ice_candidate *cand=0;
+ int i;
+ int j;
+ int r,_status;
+ int so_sock_ct=0;
+ int backlog=10;
+ char ice_tcp_disabled=1;
+
+ r_log(LOG_ICE,LOG_DEBUG,"nr_ice_component_initialize_tcp");
+
+ if(r=NR_reg_get_int4(NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,&so_sock_ct)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ if(r=NR_reg_get_int4(NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG,&backlog)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ if ((r=NR_reg_get_char(NR_ICE_REG_ICE_TCP_DISABLE, &ice_tcp_disabled))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+ if ((ctx->flags & NR_ICE_CTX_FLAGS_RELAY_ONLY) ||
+ (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_PROXY)) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): relay/proxy only option results in ICE TCP being disabled",ctx->label);
+ ice_tcp_disabled = 1;
+ }
+
+ for(i=0;i<addr_ct;i++){
+ char suppress;
+ nr_ice_socket *isock_psv=0;
+ nr_ice_socket *isock_so=0;
+
+ if(r=NR_reg_get2_char(NR_ICE_REG_SUPPRESS_INTERFACE_PRFX,addrs[i].addr.ifname,&suppress)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+ else if(suppress) {
+ continue;
+ }
+
+ if (!ice_tcp_disabled) {
+ /* passive host candidate */
+ if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
+ TCP_TYPE_PASSIVE, backlog, 0, lufrag, pwd, &isock_psv))) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): failed to create passive TCP host candidate: %d",ctx->label,r);
+ }
+
+ /* active host candidate */
+ if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
+ TCP_TYPE_ACTIVE, 0, 0, lufrag, pwd, NULL))) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): failed to create active TCP host candidate: %d",ctx->label,r);
+ }
+
+ /* simultaneous-open host candidate */
+ if (so_sock_ct) {
+ if ((r=nr_ice_component_create_tcp_host_candidate(ctx, component, &addrs[i].addr,
+ TCP_TYPE_SO, 0, so_sock_ct, lufrag, pwd, &isock_so))) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): failed to create simultanous open TCP host candidate: %d",ctx->label,r);
+ }
+ }
+
+ /* And srvrflx candidates for each STUN server */
+ for(j=0;j<ctx->stun_server_ct;j++){
+ if (ctx->stun_servers[j].transport!=IPPROTO_TCP)
+ continue;
+
+ if (isock_psv) {
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock_psv,isock_psv->sock,SERVER_REFLEXIVE,TCP_TYPE_PASSIVE,
+ &ctx->stun_servers[j],component->component_id,&cand))
+ ABORT(r);
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+ }
+
+ if (isock_so) {
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock_so,isock_so->sock,SERVER_REFLEXIVE,TCP_TYPE_SO,
+ &ctx->stun_servers[j],component->component_id,&cand))
+ ABORT(r);
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+ }
+ }
+ }
+
+#ifdef USE_TURN
+ /* Create a new relayed candidate for each addr/TURN server pair */
+ for(j=0;j<ctx->turn_server_ct;j++){
+ nr_transport_addr addr;
+ nr_socket *local_sock;
+ nr_socket *buffered_sock;
+ nr_socket *turn_sock;
+ nr_ice_socket *turn_isock;
+
+ /* Skip non-TCP */
+ if (ctx->turn_servers[j].turn_server.transport != IPPROTO_TCP)
+ continue;
+
+ if (ctx->turn_servers[j].turn_server.type == NR_ICE_STUN_SERVER_TYPE_ADDR &&
+ nr_transport_addr_cmp(&ctx->turn_servers[j].turn_server.u.addr,
+ &addrs[i].addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_VERSION)) {
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): Skipping TURN server because of IP version mis-match (%u - %u)",ctx->label,addrs[i].addr.ip_version,ctx->turn_servers[j].turn_server.u.addr.ip_version);
+ continue;
+ }
+
+ if (!ice_tcp_disabled) {
+ /* Use TURN server to get srflx candidates */
+ if (isock_psv) {
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock_psv,isock_psv->sock,SERVER_REFLEXIVE,TCP_TYPE_PASSIVE,
+ &ctx->turn_servers[j].turn_server,component->component_id,&cand))
+ ABORT(r);
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+ }
+
+ if (isock_so) {
+ if(r=nr_ice_candidate_create(ctx,component,
+ isock_so,isock_so->sock,SERVER_REFLEXIVE,TCP_TYPE_SO,
+ &ctx->turn_servers[j].turn_server,component->component_id,&cand))
+ ABORT(r);
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+ }
+ }
+
+ /* Create relay candidate */
+ if ((r=nr_transport_addr_copy(&addr, &addrs[i].addr)))
+ ABORT(r);
+ addr.protocol = IPPROTO_TCP;
+ if ((r=nr_transport_addr_fmt_addr_string(&addr)))
+ ABORT(r);
+ /* Create a local socket */
+ if((r=nr_socket_factory_create_socket(ctx->socket_factory,&addr,&local_sock))){
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): couldn't create socket for address %s",ctx->label,addr.as_string);
+ continue;
+ }
+
+ r_log(LOG_ICE,LOG_DEBUG,"nr_ice_component_initialize_tcp creating TURN TCP wrappers");
+
+ if (ctx->turn_tcp_socket_wrapper) {
+ /* The HTTP proxy socket */
+ if((r=nr_socket_wrapper_factory_wrap(ctx->turn_tcp_socket_wrapper, local_sock, &local_sock)))
+ ABORT(r);
+ }
+
+ /* The TCP buffered socket */
+ if((r=nr_socket_buffered_stun_create(local_sock, NR_STUN_MAX_MESSAGE_SIZE, TURN_TCP_FRAMING, &buffered_sock)))
+ ABORT(r);
+
+ /* The TURN socket */
+ if(r=nr_socket_turn_create(buffered_sock, &turn_sock))
+ ABORT(r);
+
+ /* Create an ICE socket */
+ if((r=nr_ice_socket_create(ctx, component, buffered_sock, NR_ICE_SOCKET_TYPE_STREAM_TURN, &turn_isock)))
+ ABORT(r);
+
+ /* Attach ourselves to it */
+ if(r=nr_ice_candidate_create(ctx,component,
+ turn_isock,turn_sock,RELAYED,TCP_TYPE_NONE,
+ &ctx->turn_servers[j].turn_server,component->component_id,&cand))
+ ABORT(r);
+ cand->u.relayed.srvflx_candidate=NULL;
+ cand->u.relayed.server=&ctx->turn_servers[j];
+ TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
+ component->candidate_ct++;
+ cand=0;
+
+ /* Create a STUN server context for this socket */
+ if ((r=nr_ice_component_create_stun_server_ctx(component,turn_isock,local_sock,&addr,lufrag,pwd)))
+ ABORT(r);
+
+ STAILQ_INSERT_TAIL(&component->sockets,turn_isock,entry);
+ }
+#endif /* USE_TURN */
+ }
+
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
+
+/* Make all the candidates we can make at the beginning */
+int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component)
+ {
+ int r,_status;
+ nr_local_addr *addrs=ctx->local_addrs;
+ int addr_ct=ctx->local_addr_ct;
+ char *lufrag;
+ char *lpwd;
+ Data pwd;
+ nr_ice_candidate *cand;
+
+ if (component->candidate_ct) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): component with id %d already has candidates, probably restarting gathering because of a new stream",ctx->label,component->component_id);
+ return(0);
+ }
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): initializing component with id %d",ctx->label,component->component_id);
+
+ if(addr_ct==0){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): no local addresses available",ctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ /* Note: we need to recompute these because
+ we have not yet computed the values in the peer media stream.*/
+ lufrag=component->stream->ufrag ? component->stream->ufrag : ctx->ufrag;
+ assert(lufrag);
+ if (!lufrag)
+ ABORT(R_INTERNAL);
+ lpwd=component->stream->pwd ? component->stream->pwd :ctx->pwd;
+ assert(lpwd);
+ if (!lpwd)
+ ABORT(R_INTERNAL);
+ INIT_DATA(pwd, (UCHAR *)lpwd, strlen(lpwd));
+
+ /* Initialize the UDP candidates */
+ if (r=nr_ice_component_initialize_udp(ctx, component, addrs, addr_ct, lufrag, &pwd))
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): failed to create UDP candidates with error %d",ctx->label,r);
+ /* And the TCP candidates */
+ if (r=nr_ice_component_initialize_tcp(ctx, component, addrs, addr_ct, lufrag, &pwd))
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): failed to create TCP candidates with error %d",ctx->label,r);
+
+ /* count the candidates that will be initialized */
+ cand=TAILQ_FIRST(&component->candidates);
+ if(!cand){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): couldn't create any valid candidates",ctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ while(cand){
+ ctx->uninitialized_candidates++;
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ /* Now initialize all the candidates */
+ cand=TAILQ_FIRST(&component->candidates);
+ while(cand){
+ if(cand->state!=NR_ICE_CAND_STATE_INITIALIZING){
+ nr_ice_candidate_initialize(cand,nr_ice_gather_finished_cb,cand);
+ }
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_any_peer_paired(nr_ice_candidate* cand) {
+ nr_ice_peer_ctx* pctx=STAILQ_FIRST(&cand->ctx->peers);
+ while(pctx && pctx->state == NR_ICE_PEER_STATE_UNPAIRED){
+ /* Is it worth actually looking through the check lists? Probably not. */
+ pctx=STAILQ_NEXT(pctx,entry);
+ }
+ return pctx != NULL;
+}
+
+/*
+ Compare this newly initialized candidate against the other initialized
+ candidates and discard the lower-priority one if they are redundant.
+
+ This algorithm combined with the other algorithms, favors
+ host > srflx > relay
+ */
+int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned)
+ {
+ nr_ice_candidate *c2, *tmp = NULL;
+
+ *was_pruned = 0;
+ c2 = TAILQ_FIRST(&comp->candidates);
+ while(c2){
+ if((c1 != c2) &&
+ (c2->state == NR_ICE_CAND_STATE_INITIALIZED) &&
+ !nr_transport_addr_cmp(&c1->base,&c2->base,NR_TRANSPORT_ADDR_CMP_MODE_ALL) &&
+ !nr_transport_addr_cmp(&c1->addr,&c2->addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
+
+ if((c1->type == c2->type) ||
+ (!(ctx->flags & NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES) &&
+ ((c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
+ (c2->type==HOST && c1->type == SERVER_REFLEXIVE)))){
+
+ /*
+ These are redundant. Remove the lower pri one, or if pairing has
+ already occurred, remove the newest one.
+
+ Since this algorithmis run whenever a new candidate
+ is initialized, there should at most one duplicate.
+ */
+ if ((c1->priority <= c2->priority) || nr_ice_any_peer_paired(c2)) {
+ tmp = c1;
+ *was_pruned = 1;
+ }
+ else {
+ tmp = c2;
+ }
+ break;
+ }
+ }
+
+ c2=TAILQ_NEXT(c2,entry_comp);
+ }
+
+ if (tmp) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): Removing redundant candidate",
+ ctx->label,tmp->label);
+
+ TAILQ_REMOVE(&comp->candidates,tmp,entry_comp);
+ comp->candidate_ct--;
+ TAILQ_REMOVE(&tmp->isock->candidates,tmp,entry_sock);
+
+ nr_ice_candidate_destroy(&tmp);
+ }
+
+ return 0;
+ }
+
+static int nr_ice_component_pair_matches_check(nr_ice_component *comp, nr_ice_cand_pair *pair, nr_transport_addr *local_addr, nr_stun_server_request *req)
+ {
+ if(pair->remote->component->component_id!=comp->component_id)
+ return(0);
+
+ if(nr_transport_addr_cmp(&pair->local->base,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ return(0);
+
+ if(nr_transport_addr_cmp(&pair->remote->addr,&req->src_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ return(0);
+
+ return(1);
+ }
+
+static int nr_ice_component_handle_triggered_check(nr_ice_component *comp, nr_ice_cand_pair *pair, nr_stun_server_request *req, int *error)
+ {
+ nr_stun_message *sreq=req->request;
+ int r=0,_status;
+
+ if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_USE_CANDIDATE,0)){
+ if(comp->stream->pctx->controlling){
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND_PAIR(%s): Peer sent USE-CANDIDATE but is controlled",comp->stream->pctx->label, pair->codeword);
+ }
+ else{
+ /* If this is the first time we've noticed this is nominated...*/
+ pair->peer_nominated=1;
+
+ if(pair->state==NR_ICE_PAIR_STATE_SUCCEEDED && !pair->nominated){
+ pair->nominated=1;
+
+ if(r=nr_ice_component_nominated_pair(pair->remote->component, pair)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+ }
+ }
+ }
+
+ /* Note: the RFC says to trigger first and then nominate. But in that case
+ * the canceled trigger pair would get nominated and the cloned trigger pair
+ * would not get the nomination status cloned with it.*/
+ if(r=nr_ice_candidate_pair_do_triggered_check(comp->stream->pctx,pair)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(r);
+ }
+
+/* Section 7.2.1 */
+static int nr_ice_component_process_incoming_check(nr_ice_component *comp, nr_transport_addr *local_addr, nr_stun_server_request *req, int *error)
+ {
+ nr_ice_cand_pair *pair;
+ nr_ice_candidate *pcand=0;
+ nr_stun_message *sreq=req->request;
+ nr_stun_message_attribute *attr;
+ int r=0,_status;
+ int found_valid=0;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): received request from %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,req->src_addr.as_string);
+
+ if (comp->state == NR_ICE_COMPONENT_DISABLED)
+ ABORT(R_REJECTED);
+
+ /* Check for role conficts (7.2.1.1) */
+ if(comp->stream->pctx->controlling){
+ if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_ICE_CONTROLLING,&attr)){
+ /* OK, there is a conflict. Who's right? */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): role conflict, both controlling",comp->stream->pctx->label);
+
+ if(attr->u.ice_controlling > comp->stream->pctx->tiebreaker){
+ /* Update the peer ctx. This will propagate to all candidate pairs
+ in the context. */
+ nr_ice_peer_ctx_switch_controlling_role(comp->stream->pctx);
+ }
+ else {
+ /* We are: throw an error */
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): returning 487 role conflict",comp->stream->pctx->label);
+
+ *error=487;
+ ABORT(R_REJECTED);
+ }
+ }
+ }
+ else{
+ if(nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_ICE_CONTROLLED,&attr)){
+ /* OK, there is a conflict. Who's right? */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): role conflict, both controlled",comp->stream->pctx->label);
+
+ if(attr->u.ice_controlled < comp->stream->pctx->tiebreaker){
+ /* Update the peer ctx. This will propagate to all candidate pairs
+ in the context. */
+ nr_ice_peer_ctx_switch_controlling_role(comp->stream->pctx);
+ }
+ else {
+ /* We are: throw an error */
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): returning 487 role conflict",comp->stream->pctx->label);
+
+ *error=487;
+ ABORT(R_REJECTED);
+ }
+ }
+ }
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): This STUN request appears to map to local addr %s",comp->stream->pctx->label,local_addr->as_string);
+
+ pair=TAILQ_FIRST(&comp->stream->check_list);
+ while(pair){
+ /* Since triggered checks create duplicate pairs (in this implementation)
+ * we are willing to handle multiple matches here. */
+ if(nr_ice_component_pair_matches_check(comp, pair, local_addr, req)){
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND_PAIR(%s): Found a matching pair for received check: %s",comp->stream->pctx->label,pair->codeword,pair->as_string);
+ if(r=nr_ice_component_handle_triggered_check(comp, pair, req, error))
+ ABORT(r);
+ ++found_valid;
+ }
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ if(!found_valid){
+ /* There were no matching pairs, so we need to create a new peer
+ * reflexive candidate pair. */
+
+ if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
+ *error=400;
+ ABORT(R_BAD_DATA);
+ }
+
+ /* Find our local component candidate */
+ nr_ice_candidate *cand;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): no matching pair",comp->stream->pctx->label);
+ cand=TAILQ_FIRST(&comp->local_component->candidates);
+ while(cand){
+ if(!nr_transport_addr_cmp(&cand->addr,local_addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ break;
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ /* Well, this really shouldn't happen, but it's an error from the
+ other side, so we just throw an error and keep going */
+ if(!cand){
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): stun request to unknown local address %s, discarding",comp->stream->pctx->label,local_addr->as_string);
+
+ *error=400;
+ ABORT(R_NOT_FOUND);
+ }
+
+ /* Now make a peer reflexive (remote) candidate */
+ if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+ pcand->priority=attr->u.priority;
+ pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
+
+ /* Finally, create the candidate pair, insert into the check list, and
+ * apply the incoming check to it. */
+ if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
+ &pair)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
+ if(r=nr_ice_component_insert_pair(comp,pair)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ nr_ice_candidate_pair_destroy(&pair);
+ ABORT(r);
+ }
+
+ /* Do this last, since any call to ABORT will destroy pcand */
+ TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
+ pcand=0;
+
+ /* Finally start the trigger check if needed */
+ if(r=nr_ice_component_handle_triggered_check(comp, pair, req, error))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_ice_candidate_destroy(&pcand);
+ assert(*error != 0);
+ if(r!=R_NO_MEMORY) assert(*error != 500);
+ }
+ return(_status);
+ }
+
+static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
+ {
+ nr_ice_component *comp=cb_arg;
+ nr_transport_addr local_addr;
+ int r,_status;
+
+ if(comp->state==NR_ICE_COMPONENT_FAILED) {
+ *error=400;
+ ABORT(R_REJECTED);
+ }
+
+ /* Find the candidate pair that this maps to */
+ if(r=nr_socket_getaddr(sock,&local_addr)) {
+ *error=500;
+ ABORT(r);
+ }
+
+ if (r=nr_ice_component_process_incoming_check(comp, &local_addr, req, error))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced)
+ {
+ nr_ice_pre_answer_request *r1,*r2;
+ nr_ice_component *comp = pcomp->local_component;
+ int r,_status;
+
+ if (serviced)
+ *serviced = 0;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): looking for pre-answer requests",pctx->label,comp->stream->label,comp->component_id);
+
+ STAILQ_FOREACH_SAFE(r1, &comp->pre_answer_reqs, entry, r2) {
+ if (!strcmp(r1->username, username)) {
+ int error = 0;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): found pre-answer request",pctx->label,comp->stream->label,comp->component_id);
+ r = nr_ice_component_process_incoming_check(pcomp, &r1->local_addr, &r1->req, &error);
+ if (r) {
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): error processing pre-answer request. Would have returned %d",pctx->label,comp->stream->label,comp->component_id, error);
+ }
+ (*serviced)++;
+ STAILQ_REMOVE(&comp->pre_answer_reqs,r1,nr_ice_pre_answer_request_, entry);
+ nr_ice_pre_answer_request_destroy(&r1);
+ }
+ }
+
+ _status=0;
+ return(_status);
+ }
+
+int nr_ice_component_can_candidate_tcptype_pair(nr_socket_tcp_type left, nr_socket_tcp_type right)
+ {
+ if (left && !right)
+ return(0);
+ if (!left && right)
+ return(0);
+ if (left == TCP_TYPE_ACTIVE && right != TCP_TYPE_PASSIVE)
+ return(0);
+ if (left == TCP_TYPE_SO && right != TCP_TYPE_SO)
+ return(0);
+ if (left == TCP_TYPE_PASSIVE)
+ return(0);
+
+ return(1);
+ }
+
+/* filter out pairings which won't work. */
+int nr_ice_component_can_candidate_addr_pair(nr_transport_addr *local, nr_transport_addr *remote)
+ {
+ if(local->ip_version != remote->ip_version)
+ return(0);
+ if(nr_transport_addr_is_link_local(local) !=
+ nr_transport_addr_is_link_local(remote))
+ return(0);
+ /* This prevents our ice_unittest (or broken clients) from pairing a
+ * loopback with a host candidate. */
+ if(nr_transport_addr_is_loopback(local) !=
+ nr_transport_addr_is_loopback(remote))
+ return(0);
+
+ return(1);
+ }
+
+int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote)
+ {
+ int r, _status;
+ nr_ice_candidate *pcand;
+ nr_ice_cand_pair *pair=0;
+ char codeword[5];
+
+ nr_ice_compute_codeword(lcand->label,strlen(lcand->label),codeword);
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND(%s): Pairing local candidate %s",pctx->label,codeword,lcand->label);
+
+ switch(lcand->type){
+ case HOST:
+ break;
+ case SERVER_REFLEXIVE:
+ case PEER_REFLEXIVE:
+ /* Don't actually pair these candidates */
+ goto done;
+ break;
+ case RELAYED:
+ break;
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ TAILQ_FOREACH(pcand, &pcomp->candidates, entry_comp){
+ if(!nr_ice_component_can_candidate_addr_pair(&lcand->addr, &pcand->addr))
+ continue;
+ if(!nr_ice_component_can_candidate_tcptype_pair(lcand->tcp_type, pcand->tcp_type))
+ continue;
+
+ /*
+ Two modes, depending on |pair_all_remote|
+
+ 1. Pair remote candidates which have not been paired
+ (used in initial pairing or in processing the other side's
+ trickle candidates).
+ 2. Pair any remote candidate (used when processing our own
+ trickle candidates).
+ */
+ if (pair_all_remote || (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED)) {
+ if (pair_all_remote) {
+ /* When a remote candidate arrives after the start of checking, but
+ * before the gathering of local candidates, it can be in UNPAIRED */
+ pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
+ }
+
+ nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND(%s): Pairing with peer candidate %s", pctx->label, codeword, pcand->label);
+
+ if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
+ ABORT(r);
+
+ if(r=nr_ice_component_insert_pair(pcomp, pair))
+ ABORT(r);
+ }
+ }
+
+ done:
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp)
+ {
+ nr_ice_candidate *lcand, *pcand;
+ nr_ice_socket *isock;
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_DEBUG,"Pairing candidates======");
+
+ /* Create the candidate pairs */
+ lcand=TAILQ_FIRST(&lcomp->candidates);
+
+ if (!lcand) {
+ /* No local candidates, initialized or not! */
+ ABORT(R_FAILED);
+ }
+
+ while(lcand){
+ if (lcand->state == NR_ICE_CAND_STATE_INITIALIZED) {
+ if ((r = nr_ice_component_pair_candidate(pctx, pcomp, lcand, 0)))
+ ABORT(r);
+ }
+
+ lcand=TAILQ_NEXT(lcand,entry_comp);
+ }
+
+ /* Mark all peer candidates as paired */
+ pcand=TAILQ_FIRST(&pcomp->candidates);
+ while(pcand){
+ pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
+
+ pcand=TAILQ_NEXT(pcand,entry_comp);
+
+ }
+
+ /* Now register the STUN server callback for this component.
+ Note that this is a per-component CB so we only need to
+ do this once.
+ */
+ if (pcomp->state != NR_ICE_COMPONENT_RUNNING) {
+ isock=STAILQ_FIRST(&lcomp->sockets);
+ while(isock){
+ if(r=nr_stun_server_add_client(isock->stun_server,pctx->label,
+ pcomp->stream->r2l_user,&pcomp->stream->r2l_pass,nr_ice_component_stun_server_cb,pcomp)) {
+ ABORT(r);
+ }
+ isock=STAILQ_NEXT(isock,entry);
+ }
+ }
+
+ pcomp->state = NR_ICE_COMPONENT_RUNNING;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_pre_answer_enqueue(nr_ice_component *comp, nr_socket *sock, nr_stun_server_request *req, int *dont_free)
+ {
+ int r = 0;
+ int _status;
+ nr_ice_pre_answer_request *r1, *r2;
+ nr_transport_addr dst_addr;
+ nr_ice_pre_answer_request *par = 0;
+
+ if (r=nr_socket_getaddr(sock, &dst_addr))
+ ABORT(r);
+
+ STAILQ_FOREACH_SAFE(r1, &comp->pre_answer_reqs, entry, r2) {
+ if (!nr_transport_addr_cmp(&r1->local_addr, &dst_addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL) &&
+ !nr_transport_addr_cmp(&r1->req.src_addr, &req->src_addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ return(0);
+ }
+ }
+
+ if (r=nr_ice_pre_answer_request_create(&dst_addr, req, &par))
+ ABORT(r);
+
+ r_log(LOG_ICE,LOG_DEBUG, "ICE(%s)/STREAM(%s)/COMP(%d): Enqueuing STUN request pre-answer from %s",
+ comp->ctx->label, comp->stream->label, comp->component_id,
+ req->src_addr.as_string);
+
+ *dont_free = 1;
+ STAILQ_INSERT_TAIL(&comp->pre_answer_reqs, par, entry);
+
+ _status=0;
+abort:
+ return(_status);
+ }
+
+/* Fires when we have an incoming candidate that doesn't correspond to an existing
+ remote peer. This is either pre-answer or just spurious. Store it in the
+ component for use when we see the actual answer, at which point we need
+ to do the procedures from S 7.2.1 in nr_ice_component_stun_server_cb.
+ */
+static int nr_ice_component_stun_server_default_cb(void *cb_arg,nr_stun_server_ctx *stun_ctx,nr_socket *sock, nr_stun_server_request *req, int *dont_free, int *error)
+ {
+ int r, _status;
+ nr_ice_component *comp = (nr_ice_component *)cb_arg;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/STREAM(%s)/COMP(%d): Received STUN request pre-answer from %s",
+ comp->ctx->label, comp->stream->label, comp->component_id,
+ req->src_addr.as_string);
+
+ if (r=nr_ice_pre_answer_enqueue(comp, sock, req, dont_free)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s)/STREAM(%s)/COMP(%d): Failed (%d) to enque pre-answer request from %s",
+ comp->ctx->label, comp->stream->label, comp->component_id, r,
+ req->src_addr.as_string);
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+#define NR_ICE_CONSENT_TIMER_DEFAULT 5000
+#define NR_ICE_CONSENT_TIMEOUT_DEFAULT 30000
+
+static void nr_ice_component_consent_failed(nr_ice_component *comp)
+ {
+ if (!comp->can_send) {
+ return;
+ }
+
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s)/STREAM(%s)/COMP(%d): Consent refresh failed",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ comp->can_send = 0;
+
+ if (comp->consent_timeout) {
+ NR_async_timer_cancel(comp->consent_timeout);
+ comp->consent_timeout = 0;
+ }
+ if (comp->consent_timer) {
+ NR_async_timer_cancel(comp->consent_timer);
+ comp->consent_timer = 0;
+ }
+ /* We are turning the consent failure into a ICE component failure to
+ * alert the browser via ICE connection state change about this event. */
+ if (nr_ice_media_stream_component_failed(comp->stream, comp))
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s)/STREAM(%s)/COMP(%d): failed to mark component as failed",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ }
+
+static void nr_ice_component_consent_timeout_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_component *comp=cb_arg;
+
+ comp->consent_timeout = 0;
+
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s)/STREAM(%s)/COMP(%d): Consent refresh final time out",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ nr_ice_component_consent_failed(comp);
+ }
+
+
+static void nr_ice_component_consent_request_timed_out(nr_ice_component *comp)
+ {
+ if (!comp->can_send) {
+ return;
+ }
+
+ nr_ice_peer_ctx_disconnected(comp->stream->pctx);
+ }
+
+static void nr_ice_component_consent_refreshed(nr_ice_component *comp)
+ {
+ uint16_t tval;
+
+ if (!comp->can_send) {
+ return;
+ }
+
+ gettimeofday(&comp->consent_last_seen, 0);
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/STREAM(%s)/COMP(%d): consent_last_seen is now %lu",
+ comp->ctx->label, comp->stream->label, comp->component_id,
+ comp->consent_last_seen.tv_sec);
+
+ nr_ice_peer_ctx_connected(comp->stream->pctx);
+
+ if (comp->consent_timeout)
+ NR_async_timer_cancel(comp->consent_timeout);
+
+ tval = NR_ICE_CONSENT_TIMEOUT_DEFAULT;
+ if (comp->ctx->test_timer_divider)
+ tval = tval / comp->ctx->test_timer_divider;
+
+ NR_ASYNC_TIMER_SET(tval, nr_ice_component_consent_timeout_cb, comp,
+ &comp->consent_timeout);
+ }
+
+static void nr_ice_component_refresh_consent_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_component *comp=cb_arg;
+
+ switch (comp->consent_ctx->state) {
+ case NR_STUN_CLIENT_STATE_FAILED:
+ if (comp->consent_ctx->error_code == 403) {
+ r_log(LOG_ICE, LOG_INFO, "ICE(%s)/STREAM(%s)/COMP(%d): Consent revoked by peer",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ nr_ice_component_consent_failed(comp);
+ }
+ break;
+ case NR_STUN_CLIENT_STATE_DONE:
+ r_log(LOG_ICE, LOG_INFO, "ICE(%s)/STREAM(%s)/COMP(%d): Consent refreshed",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ nr_ice_component_consent_refreshed(comp);
+ break;
+ case NR_STUN_CLIENT_STATE_TIMED_OUT:
+ r_log(LOG_ICE, LOG_INFO, "ICE(%s)/STREAM(%s)/COMP(%d): A single consent refresh request timed out",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+ nr_ice_component_consent_request_timed_out(comp);
+ break;
+ default:
+ break;
+ }
+ }
+
+int nr_ice_component_refresh_consent(nr_stun_client_ctx *ctx, NR_async_cb finished_cb, void *cb_arg)
+ {
+ int r,_status;
+
+ nr_stun_client_reset(ctx);
+
+ if (r=nr_stun_client_start(ctx, NR_ICE_CLIENT_MODE_BINDING_REQUEST, finished_cb, cb_arg))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+void nr_ice_component_consent_calc_consent_timer(nr_ice_component *comp)
+ {
+ uint16_t trange, trand, tval;
+
+ trange = NR_ICE_CONSENT_TIMER_DEFAULT * 20 / 100;
+ tval = NR_ICE_CONSENT_TIMER_DEFAULT - trange;
+ if (!nr_crypto_random_bytes((UCHAR*)&trand, sizeof(trand)))
+ tval += (trand % (trange * 2));
+
+ if (comp->ctx->test_timer_divider)
+ tval = tval / comp->ctx->test_timer_divider;
+
+ /* The timeout of the transaction is the maximum time until we send the
+ * next consent request. */
+ comp->consent_ctx->maximum_transmits_timeout_ms = tval;
+ }
+
+static void nr_ice_component_consent_timer_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_component *comp=cb_arg;
+ int r;
+
+ comp->consent_timer = 0;
+
+ comp->consent_ctx->params.ice_binding_request.username =
+ comp->stream->l2r_user;
+ comp->consent_ctx->params.ice_binding_request.password =
+ comp->stream->l2r_pass;
+ comp->consent_ctx->params.ice_binding_request.control =
+ comp->stream->pctx->controlling?
+ NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
+ comp->consent_ctx->params.ice_binding_request.tiebreaker =
+ comp->stream->pctx->tiebreaker;
+ comp->consent_ctx->params.ice_binding_request.priority =
+ comp->active->local->priority;
+
+ nr_ice_component_consent_calc_consent_timer(comp);
+
+ if (r=nr_ice_component_refresh_consent(comp->consent_ctx,
+ nr_ice_component_refresh_consent_cb,
+ comp)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s)/STREAM(%s)/COMP(%d): Refresh consent failed with %d",
+ comp->ctx->label, comp->stream->label, comp->component_id, r);
+ /* In case our attempt to send the refresh binding request reports an
+ * error we don't have to wait for timeouts, but declare this connection
+ * dead right away. */
+ if (r != R_WOULDBLOCK) {
+ nr_ice_component_consent_failed(comp);
+ }
+ }
+
+ nr_ice_component_consent_schedule_consent_timer(comp);
+
+ }
+
+void nr_ice_component_consent_schedule_consent_timer(nr_ice_component *comp)
+ {
+ if (!comp->can_send) {
+ return;
+ }
+
+ NR_ASYNC_TIMER_SET(comp->consent_ctx->maximum_transmits_timeout_ms,
+ nr_ice_component_consent_timer_cb, comp,
+ &comp->consent_timer);
+ }
+
+void nr_ice_component_consent_destroy(nr_ice_component *comp)
+ {
+ if (comp->consent_timer) {
+ NR_async_timer_cancel(comp->consent_timer);
+ comp->consent_timer = 0;
+ }
+ if (comp->consent_timeout) {
+ NR_async_timer_cancel(comp->consent_timeout);
+ comp->consent_timeout = 0;
+ }
+ if (comp->consent_handle) {
+ nr_ice_socket_deregister(comp->active->local->isock,
+ comp->consent_handle);
+ comp->consent_handle = 0;
+ }
+ if (comp->consent_ctx) {
+ nr_stun_client_ctx_destroy(&comp->consent_ctx);
+ }
+ }
+
+int nr_ice_component_setup_consent(nr_ice_component *comp)
+ {
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/STREAM(%s)/COMP(%d): Setting up refresh consent",
+ comp->ctx->label, comp->stream->label, comp->component_id);
+
+ if (r=nr_stun_client_ctx_create("consent", comp->active->local->osock,
+ &comp->active->remote->addr, 0,
+ &comp->consent_ctx))
+ ABORT(r);
+ /* Consent request get send only once. */
+ comp->consent_ctx->maximum_transmits = 1;
+
+ if (r=nr_ice_socket_register_stun_client(comp->active->local->isock,
+ comp->consent_ctx, &comp->consent_handle))
+ ABORT(r);
+
+ comp->can_send = 1;
+ nr_ice_component_consent_refreshed(comp);
+
+ nr_ice_component_consent_calc_consent_timer(comp);
+ nr_ice_component_consent_schedule_consent_timer(comp);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+ nr_ice_cand_pair *p2;
+
+ /* Are we changing what the nominated pair is? */
+ if(comp->nominated){
+ if(comp->nominated->priority >= pair->priority)
+ return(0);
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): replacing pair %s with CAND-PAIR(%s)",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->codeword,comp->nominated->as_string,pair->codeword);
+ /* As consent doesn't hold a reference to its isock this needs to happen
+ * before making the new pair the active one. */
+ nr_ice_component_consent_destroy(comp);
+ }
+
+ /* Set the new nominated pair */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): nominated pair is %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->codeword,pair->as_string);
+ comp->state=NR_ICE_COMPONENT_NOMINATED;
+ comp->nominated=pair;
+ comp->active=pair;
+
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling all pairs but %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->codeword,pair->as_string);
+
+ /* Cancel checks in WAITING and FROZEN per ICE S 8.1.2 */
+ p2=TAILQ_FIRST(&comp->stream->trigger_check_queue);
+ while(p2){
+ if((p2 != pair) &&
+ (p2->remote->component->component_id == comp->component_id)) {
+ assert(p2->state == NR_ICE_PAIR_STATE_WAITING ||
+ p2->state == NR_ICE_PAIR_STATE_CANCELLED);
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s in trigger check queue because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
+
+ if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0))
+ ABORT(r);
+ }
+
+ p2=TAILQ_NEXT(p2,triggered_check_queue_entry);
+ }
+ p2=TAILQ_FIRST(&comp->stream->check_list);
+ while(p2){
+ if((p2 != pair) &&
+ (p2->remote->component->component_id == comp->component_id) &&
+ ((p2->state == NR_ICE_PAIR_STATE_FROZEN) ||
+ (p2->state == NR_ICE_PAIR_STATE_WAITING))) {
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword);
+
+ if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0))
+ ABORT(r);
+ }
+
+ p2=TAILQ_NEXT(p2,check_queue_entry);
+ }
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
+
+ if(r=nr_ice_component_setup_consent(comp))
+ ABORT(r);
+
+ if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_component_have_all_pairs_failed(nr_ice_component *comp)
+ {
+ nr_ice_cand_pair *p2;
+
+ p2=TAILQ_FIRST(&comp->stream->check_list);
+ while(p2){
+ if(comp->component_id==p2->local->component_id){
+ switch(p2->state){
+ case NR_ICE_PAIR_STATE_FROZEN:
+ case NR_ICE_PAIR_STATE_WAITING:
+ case NR_ICE_PAIR_STATE_IN_PROGRESS:
+ case NR_ICE_PAIR_STATE_SUCCEEDED:
+ return(0);
+ case NR_ICE_PAIR_STATE_FAILED:
+ case NR_ICE_PAIR_STATE_CANCELLED:
+ /* states that will never be recovered from */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ p2=TAILQ_NEXT(p2,check_queue_entry);
+ }
+
+ return(1);
+ }
+
+int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
+ {
+ return nr_ice_component_check_if_failed(comp);
+ }
+
+int nr_ice_component_check_if_failed(nr_ice_component *comp)
+ {
+ if (comp->state == NR_ICE_COMPONENT_RUNNING) {
+ /* Don't do anything to streams that aren't currently running */
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): Checking whether component needs to be marked failed.",comp->stream->pctx->label,comp->stream->label,comp->component_id);
+
+ if (!comp->stream->pctx->trickle_grace_period_timer &&
+ nr_ice_component_have_all_pairs_failed(comp)) {
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): All pairs are failed, and grace period has elapsed. Marking component as failed.",comp->stream->pctx->label,comp->stream->label,comp->component_id);
+ return nr_ice_media_stream_component_failed(comp->stream,comp);
+ }
+ }
+
+ return(0);
+ }
+
+int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp)
+ {
+ nr_ice_cand_pair **pairs=0;
+ int ct=0;
+ nr_ice_cand_pair *pair;
+ int r,_status;
+
+ /* Size the array */
+ pair=TAILQ_FIRST(&comp->stream->check_list);
+ while(pair){
+ if (comp->component_id == pair->local->component_id)
+ ct++;
+
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ /* Make and fill the array */
+ if(!(pairs=RCALLOC(sizeof(nr_ice_cand_pair *)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ ct=0;
+ pair=TAILQ_FIRST(&comp->stream->check_list);
+ while(pair){
+ if (comp->component_id == pair->local->component_id)
+ pairs[ct++]=pair;
+
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ if (pctx->handler) {
+ if(r=pctx->handler->vtbl->select_pair(pctx->handler->obj,
+ comp->stream,comp->component_id,pairs,ct))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ RFREE(pairs);
+ return(_status);
+ }
+
+
+/* Close the underlying sockets for everything but the nominated candidate */
+int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp)
+ {
+ nr_ice_socket *isock=0;
+ nr_ice_socket *s1,*s2;
+
+ if(rcomp->state==NR_ICE_COMPONENT_NOMINATED){
+ assert(rcomp->active == rcomp->nominated);
+ isock=rcomp->nominated->local->isock;
+ }
+
+ STAILQ_FOREACH_SAFE(s1, &lcomp->sockets, entry, s2){
+ if(s1!=isock){
+ STAILQ_REMOVE(&lcomp->sockets,s1,nr_ice_socket_,entry);
+ nr_ice_socket_destroy(&s1);
+ }
+ }
+
+ return(0);
+ }
+
+
+int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+
+ /* Pairs for peer reflexive are marked SUCCEEDED immediately */
+ if (pair->state != NR_ICE_PAIR_STATE_FROZEN &&
+ pair->state != NR_ICE_PAIR_STATE_SUCCEEDED){
+ assert(0);
+ ABORT(R_BAD_ARGS);
+ }
+
+ if(r=nr_ice_candidate_pair_insert(&pair->remote->stream->check_list,pair))
+ ABORT(r);
+
+ /* Make sure the check timer is running, if the stream was previously
+ * started. We will not start streams just because a pair was created,
+ * unless it is the first pair to be created across all streams. */
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND-PAIR(%s): Ensure that check timer is running for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
+
+ if(pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE ||
+ (pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN &&
+ !pair->remote->stream->pctx->checks_started)){
+ if(nr_ice_media_stream_start_checks(pair->remote->stream->pctx, pair->remote->stream)) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND-PAIR(%s): Could not restart checks for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
+ ABORT(R_INTERNAL);
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version)
+ {
+ int _status;
+ nr_ice_candidate *cand;
+ nr_ice_candidate *best_cand = NULL;
+
+ /* We have the component. Now find the "best" candidate, making
+ use of the fact that more "reliable" candidate types have
+ higher numbers. So, we sort by type and then priority within
+ type
+ */
+ cand=TAILQ_FIRST(&comp->candidates);
+ while(cand){
+ if (!nr_ice_ctx_hide_candidate(comp->ctx, cand) &&
+ cand->addr.ip_version == ip_version) {
+ if (!best_cand) {
+ best_cand = cand;
+ }
+ else if (best_cand->type < cand->type) {
+ best_cand = cand;
+ } else if (best_cand->type == cand->type &&
+ best_cand->priority < cand->priority) {
+ best_cand = cand;
+ }
+ }
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ /* No candidates */
+ if (!best_cand)
+ ABORT(R_NOT_FOUND);
+
+ *candp = best_cand;
+
+ _status=0;
+ abort:
+ return(_status);
+
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.h b/media/mtransport/third_party/nICEr/src/ice/ice_component.h
new file mode 100644
index 000000000..5bb0ea1e7
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.h
@@ -0,0 +1,104 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_component_h
+#define _ice_component_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct nr_ice_pre_answer_request_ {
+ nr_stun_server_request req;
+ char *username;
+ nr_transport_addr local_addr;
+
+ STAILQ_ENTRY(nr_ice_pre_answer_request_) entry;
+} nr_ice_pre_answer_request;
+
+typedef STAILQ_HEAD(nr_ice_pre_answer_request_head_, nr_ice_pre_answer_request_) nr_ice_pre_answer_request_head;
+
+struct nr_ice_component_ {
+ int state;
+#define NR_ICE_COMPONENT_UNPAIRED 0
+#define NR_ICE_COMPONENT_RUNNING 1
+#define NR_ICE_COMPONENT_NOMINATED 2
+#define NR_ICE_COMPONENT_FAILED 3
+#define NR_ICE_COMPONENT_DISABLED 4
+ struct nr_ice_ctx_ *ctx;
+ struct nr_ice_media_stream_ *stream;
+ nr_ice_component *local_component;
+
+ int component_id;
+ nr_ice_socket_head sockets;
+ nr_ice_candidate_head candidates;
+ int candidate_ct;
+ nr_ice_pre_answer_request_head pre_answer_reqs;
+
+ int valid_pairs;
+ struct nr_ice_cand_pair_ *nominated; /* Highest priority nomninated pair */
+ struct nr_ice_cand_pair_ *active;
+
+ nr_stun_client_ctx *consent_ctx;
+ void *consent_timer;
+ void *consent_timeout;
+ void *consent_handle;
+ int can_send;
+ struct timeval consent_last_seen;
+
+ STAILQ_ENTRY(nr_ice_component_)entry;
+};
+
+typedef STAILQ_HEAD(nr_ice_component_head_,nr_ice_component_) nr_ice_component_head;
+
+int nr_ice_component_create(struct nr_ice_media_stream_ *stream, int component_id, nr_ice_component **componentp);
+int nr_ice_component_destroy(nr_ice_component **componentp);
+int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component);
+int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned);
+int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote);
+int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp, nr_ice_component *pcomp);
+int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced);
+int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
+int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
+int nr_ice_component_check_if_failed(nr_ice_component *comp);
+int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp);
+int nr_ice_component_set_failed(nr_ice_component *comp);
+int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp);
+int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair);
+int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
new file mode 100644
index 000000000..08810a92d
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
@@ -0,0 +1,1057 @@
+
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <csi_platform.h>
+#include <assert.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <sys/queue.h>
+#include <string.h>
+#include <nr_api.h>
+#include <registry.h>
+#include "stun.h"
+#include "ice_ctx.h"
+#include "ice_reg.h"
+#include "nr_crypto.h"
+#include "async_timer.h"
+#include "util.h"
+#include "nr_socket_local.h"
+
+#define ICE_UFRAG_LEN 8
+#define ICE_PWD_LEN 32
+
+int LOG_ICE = 0;
+
+static int nr_ice_random_string(char *str, int len);
+static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
+#ifdef USE_TURN
+static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
+#endif /* USE_TURN */
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
+static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
+static int no_op(void **obj) {
+ return 0;
+}
+
+static nr_socket_factory_vtbl default_socket_factory_vtbl = {
+ nr_socket_local_create,
+ no_op
+};
+
+int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
+ {
+ int r,_status;
+ nr_ice_stun_server *servers = 0;
+ int i;
+ NR_registry child;
+ char *addr=0;
+ UINT2 port;
+ in_addr_t addr_int;
+
+ if(!(servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ for(i=0;i<ct;i++){
+ if(r=NR_reg_get_child_registry(NR_ICE_REG_STUN_SRV_PRFX,i,child))
+ ABORT(r);
+ /* Assume we have a v4 addr for now */
+ if(r=NR_reg_alloc2_string(child,"addr",&addr))
+ ABORT(r);
+ addr_int=inet_addr(addr);
+ if(addr_int==INADDR_NONE){
+ r_log(LOG_ICE,LOG_ERR,"Invalid address %s;",addr);
+ ABORT(R_BAD_ARGS);
+ }
+ if(r=NR_reg_get2_uint2(child,"port",&port)) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ port = 3478;
+ }
+ if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
+ &servers[i].u.addr))
+ ABORT(r);
+ servers[i].type = NR_ICE_STUN_SERVER_TYPE_ADDR;
+ RFREE(addr);
+ addr=0;
+ }
+
+ *out = servers;
+
+ _status=0;
+ abort:
+ RFREE(addr);
+ if (_status) RFREE(servers);
+ return(_status);
+ }
+
+int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
+ {
+ int _status;
+
+ if(ctx->stun_servers){
+ RFREE(ctx->stun_servers);
+ ctx->stun_server_ct=0;
+ }
+
+ if (ct) {
+ if(!(ctx->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ memcpy(ctx->stun_servers,servers,sizeof(nr_ice_stun_server)*ct);
+ ctx->stun_server_ct = ct;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
+ {
+ int _status;
+
+ if(ctx->turn_servers){
+ RFREE(ctx->turn_servers);
+ ctx->turn_server_ct=0;
+ }
+
+ if(ct) {
+ if(!(ctx->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ memcpy(ctx->turn_servers,servers,sizeof(nr_ice_turn_server)*ct);
+ ctx->turn_server_ct = ct;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_ctx_copy_turn_servers(nr_ice_ctx *ctx, nr_ice_turn_server *servers, int ct)
+ {
+ int _status, i, r;
+
+ if (r = nr_ice_ctx_set_turn_servers(ctx, servers, ct)) {
+ ABORT(r);
+ }
+
+ // make copies of the username and password so they aren't freed twice
+ for (i = 0; i < ct; ++i) {
+ if (!(ctx->turn_servers[i].username = r_strdup(servers[i].username))) {
+ ABORT(R_NO_MEMORY);
+ }
+ if (r = r_data_create(&ctx->turn_servers[i].password,
+ servers[i].password->data,
+ servers[i].password->len)) {
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_ctx_set_local_addrs(nr_ice_ctx *ctx,nr_local_addr *addrs,int ct)
+ {
+ int _status,i,r;
+
+ if(ctx->local_addrs) {
+ RFREE(ctx->local_addrs);
+ ctx->local_addr_ct=0;
+ ctx->local_addrs=0;
+ }
+
+ if (ct) {
+ if(!(ctx->local_addrs=RCALLOC(sizeof(nr_local_addr)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ for (i=0;i<ct;++i) {
+ if (r=nr_local_addr_copy(ctx->local_addrs+i,addrs+i)) {
+ ABORT(r);
+ }
+ }
+ ctx->local_addr_ct = ct;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver)
+ {
+ int _status;
+
+ if (ctx->resolver) {
+ ABORT(R_ALREADY);
+ }
+
+ ctx->resolver = resolver;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *ip)
+ {
+ int _status;
+
+ if (ctx->interface_prioritizer) {
+ ABORT(R_ALREADY);
+ }
+
+ ctx->interface_prioritizer = ip;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_ctx_set_turn_tcp_socket_wrapper(nr_ice_ctx *ctx, nr_socket_wrapper_factory *wrapper)
+ {
+ int _status;
+
+ if (ctx->turn_tcp_socket_wrapper) {
+ ABORT(R_ALREADY);
+ }
+
+ ctx->turn_tcp_socket_wrapper = wrapper;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory)
+ {
+ nr_socket_factory_destroy(&ctx->socket_factory);
+ ctx->socket_factory = factory;
+ }
+
+#ifdef USE_TURN
+int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
+ {
+ int r,_status;
+ nr_ice_turn_server *servers = 0;
+ int i;
+ NR_registry child;
+ char *addr=0;
+ UINT2 port;
+ in_addr_t addr_int;
+ Data data={0};
+
+ if(!(servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
+ ABORT(R_NO_MEMORY);
+
+ for(i=0;i<ct;i++){
+ if(r=NR_reg_get_child_registry(NR_ICE_REG_TURN_SRV_PRFX,i,child))
+ ABORT(r);
+ /* Assume we have a v4 addr for now */
+ if(r=NR_reg_alloc2_string(child,"addr",&addr))
+ ABORT(r);
+ addr_int=inet_addr(addr);
+ if(addr_int==INADDR_NONE){
+ r_log(LOG_ICE,LOG_ERR,"Invalid address %s",addr);
+ ABORT(R_BAD_ARGS);
+ }
+ if(r=NR_reg_get2_uint2(child,"port",&port)) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ port = 3478;
+ }
+ if(r=nr_ip4_port_to_transport_addr(ntohl(addr_int), port, IPPROTO_UDP,
+ &servers[i].turn_server.u.addr))
+ ABORT(r);
+
+
+ if(r=NR_reg_alloc2_string(child,NR_ICE_REG_TURN_SRV_USERNAME,&servers[i].username)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ if(r=NR_reg_alloc2_data(child,NR_ICE_REG_TURN_SRV_PASSWORD,&data)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+ else {
+ servers[i].password=RCALLOC(sizeof(*servers[i].password));
+ if(!servers[i].password)
+ ABORT(R_NO_MEMORY);
+ servers[i].password->data = data.data;
+ servers[i].password->len = data.len;
+ data.data=0;
+ }
+
+ RFREE(addr);
+ addr=0;
+ }
+
+ *out = servers;
+
+ _status=0;
+ abort:
+ RFREE(data.data);
+ RFREE(addr);
+ if (_status) RFREE(servers);
+ return(_status);
+ }
+#endif /* USE_TURN */
+
+#define MAXADDRS 100 /* Ridiculously high */
+int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
+ {
+ int r,_status;
+ char *ufrag = 0;
+ char *pwd = 0;
+
+ if (r=nr_ice_get_new_ice_ufrag(&ufrag))
+ ABORT(r);
+ if (r=nr_ice_get_new_ice_pwd(&pwd))
+ ABORT(r);
+
+ if (r=nr_ice_ctx_create_with_credentials(label, flags, ufrag, pwd, ctxp))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ RFREE(ufrag);
+ RFREE(pwd);
+
+ return(_status);
+ }
+
+int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char *ufrag, char *pwd, nr_ice_ctx **ctxp)
+ {
+ nr_ice_ctx *ctx=0;
+ int r,_status;
+
+ if(r=r_log_register("ice", &LOG_ICE))
+ ABORT(r);
+
+ if(!(ctx=RCALLOC(sizeof(nr_ice_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ ctx->flags=flags;
+
+ if(!(ctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ if(!(ctx->ufrag=r_strdup(ufrag)))
+ ABORT(r);
+ if(!(ctx->pwd=r_strdup(pwd)))
+ ABORT(r);
+
+ /* Get the STUN servers */
+ if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX,
+ (unsigned int *)&ctx->stun_server_ct)||ctx->stun_server_ct==0) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No STUN servers specified in nICEr registry", ctx->label);
+ ctx->stun_server_ct=0;
+ }
+
+ /* 31 is the max for our priority algorithm */
+ if(ctx->stun_server_ct>31){
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN servers specified: max=31", ctx->label);
+ ctx->stun_server_ct=31;
+ }
+
+ if(ctx->stun_server_ct>0){
+ if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct,&ctx->stun_servers)){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load STUN servers from registry", ctx->label);
+ ctx->stun_server_ct=0;
+ ABORT(r);
+ }
+ }
+
+#ifdef USE_TURN
+ /* Get the TURN servers */
+ if(r=NR_reg_get_child_count(NR_ICE_REG_TURN_SRV_PRFX,
+ (unsigned int *)&ctx->turn_server_ct)||ctx->turn_server_ct==0) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No TURN servers specified in nICEr registry", ctx->label);
+ ctx->turn_server_ct=0;
+ }
+#else
+ ctx->turn_server_ct=0;
+#endif /* USE_TURN */
+
+ ctx->local_addrs=0;
+ ctx->local_addr_ct=0;
+
+ /* 31 is the max for our priority algorithm */
+ if((ctx->stun_server_ct+ctx->turn_server_ct)>31){
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Too many STUN/TURN servers specified: max=31", ctx->label);
+ ctx->turn_server_ct=31-ctx->stun_server_ct;
+ }
+
+#ifdef USE_TURN
+ if(ctx->turn_server_ct>0){
+ if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct,&ctx->turn_servers)){
+ ctx->turn_server_ct=0;
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): Couldn't load TURN servers from registry", ctx->label);
+ ABORT(r);
+ }
+ }
+#endif /* USE_TURN */
+
+
+ ctx->Ta = 20;
+
+ ctx->test_timer_divider = 0;
+
+ if (r=nr_socket_factory_create_int(NULL, &default_socket_factory_vtbl, &ctx->socket_factory))
+ ABORT(r);
+
+ if ((r=NR_reg_get_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, ctx->force_net_interface, sizeof(ctx->force_net_interface)))) {
+ if (r == R_NOT_FOUND) {
+ ctx->force_net_interface[0] = 0;
+ } else {
+ ABORT(r);
+ }
+ }
+
+ STAILQ_INIT(&ctx->streams);
+ STAILQ_INIT(&ctx->sockets);
+ STAILQ_INIT(&ctx->foundations);
+ STAILQ_INIT(&ctx->peers);
+ STAILQ_INIT(&ctx->ids);
+
+ *ctxp=ctx;
+
+ _status=0;
+ abort:
+ if(_status && ctx)
+ nr_ice_ctx_destroy_cb(0,0,ctx);
+
+ return(_status);
+ }
+
+static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_ctx *ctx=cb_arg;
+ nr_ice_foundation *f1,*f2;
+ nr_ice_media_stream *s1,*s2;
+ int i;
+ nr_ice_stun_id *id1,*id2;
+
+ STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2){
+ STAILQ_REMOVE(&ctx->streams,s1,nr_ice_media_stream_,entry);
+ nr_ice_media_stream_destroy(&s1);
+ }
+
+ RFREE(ctx->label);
+
+ RFREE(ctx->stun_servers);
+
+ RFREE(ctx->local_addrs);
+
+ for (i = 0; i < ctx->turn_server_ct; i++) {
+ RFREE(ctx->turn_servers[i].username);
+ r_data_destroy(&ctx->turn_servers[i].password);
+ }
+ RFREE(ctx->turn_servers);
+
+ f1=STAILQ_FIRST(&ctx->foundations);
+ while(f1){
+ f2=STAILQ_NEXT(f1,entry);
+ RFREE(f1);
+ f1=f2;
+ }
+ RFREE(ctx->pwd);
+ RFREE(ctx->ufrag);
+
+ STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2){
+ STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry);
+ RFREE(id1);
+ }
+
+ nr_resolver_destroy(&ctx->resolver);
+ nr_interface_prioritizer_destroy(&ctx->interface_prioritizer);
+ nr_socket_wrapper_factory_destroy(&ctx->turn_tcp_socket_wrapper);
+ nr_socket_factory_destroy(&ctx->socket_factory);
+
+ RFREE(ctx);
+ }
+
+void nr_ice_ctx_add_flags(nr_ice_ctx *ctx, UINT4 flags)
+ {
+ ctx->flags |= flags;
+ }
+
+void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags)
+ {
+ ctx->flags &= ~flags;
+ }
+
+int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
+ {
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ (*ctxp)->done_cb=0;
+ (*ctxp)->trickle_cb=0;
+
+ NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
+
+ *ctxp=0;
+
+ return(0);
+ }
+
+void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
+ {
+ int r;
+ nr_ice_candidate *cand=cb_arg;
+ nr_ice_ctx *ctx;
+
+
+ assert(cb_arg);
+ if (!cb_arg)
+ return;
+ ctx = cand->ctx;
+
+ ctx->uninitialized_candidates--;
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/CAND(%s): initialized, %d remaining",ctx->label,cand->codeword,ctx->uninitialized_candidates);
+
+ /* Avoid the need for yet another initialization function */
+ if (cand->state == NR_ICE_CAND_STATE_INITIALIZING && cand->type == HOST)
+ cand->state = NR_ICE_CAND_STATE_INITIALIZED;
+
+ if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
+ int was_pruned = 0;
+
+ if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
+ cand, &was_pruned)) {
+ r_log(LOG_ICE, LOG_NOTICE, "ICE(%s): Problem pruning candidates",ctx->label);
+ }
+
+ /* If we are initialized, the candidate wasn't pruned,
+ and we have a trickle ICE callback fire the callback */
+ if (ctx->trickle_cb && !was_pruned &&
+ !nr_ice_ctx_hide_candidate(ctx, cand)) {
+ ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
+
+ if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
+ r_log(LOG_ICE,LOG_ERR, "ICE(%s): All could not pair new trickle candidate",ctx->label);
+ /* But continue */
+ }
+ }
+ }
+
+ if(ctx->uninitialized_candidates==0){
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
+ if (ctx->done_cb) {
+ ctx->done_cb(0,0,ctx->cb_arg);
+ }
+ else {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): No done_cb. We were probably destroyed.",ctx->label);
+ }
+ }
+ else {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Waiting for %d candidates to be initialized",ctx->label, ctx->uninitialized_candidates);
+ }
+ }
+
+static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
+ {
+ int r,_status;
+ nr_ice_peer_ctx *pctx;
+
+ pctx=STAILQ_FIRST(&ctx->peers);
+ while(pctx){
+ if (pctx->state == NR_ICE_PEER_STATE_PAIRED) {
+ r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
+ if (r)
+ ABORT(r);
+ }
+
+ pctx=STAILQ_NEXT(pctx,entry);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* Get the default address by doing a connect to a known public IP address,
+ in this case Google public DNS:
+
+ IPv4: 8.8.8.8
+ IPv6: 2001:4860:4860::8888
+
+ Then we can do getsockname to get the address. No packets get sent
+ since this is UDP. It's just a way to get the address.
+*/
+static int nr_ice_get_default_address(nr_ice_ctx *ctx, int ip_version, nr_transport_addr* addrp)
+ {
+ int r,_status;
+ nr_transport_addr addr;
+ nr_transport_addr remote_addr;
+ nr_socket *sock=0;
+
+ switch(ip_version) {
+ case NR_IPV4:
+ if ((r=nr_str_port_to_transport_addr("0.0.0.0", 0, IPPROTO_UDP, &addr)))
+ ABORT(r);
+ if ((r=nr_str_port_to_transport_addr("8.8.8.8", 53, IPPROTO_UDP, &remote_addr)))
+ ABORT(r);
+ break;
+ case NR_IPV6:
+ if ((r=nr_str_port_to_transport_addr("::0", 0, IPPROTO_UDP, &addr)))
+ ABORT(r);
+ if ((r=nr_str_port_to_transport_addr("2001:4860:4860::8888", 53, IPPROTO_UDP, &remote_addr)))
+ ABORT(r);
+ break;
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ }
+
+ if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
+ ABORT(r);
+ if ((r=nr_socket_connect(sock, &remote_addr)))
+ ABORT(r);
+ if ((r=nr_socket_getaddr(sock, addrp)))
+ ABORT(r);
+
+ r_log(LOG_GENERIC, LOG_DEBUG, "Default address: %s", addrp->as_string);
+
+ _status=0;
+ abort:
+ nr_socket_destroy(&sock);
+ return(_status);
+ }
+
+static int nr_ice_get_default_local_address(nr_ice_ctx *ctx, int ip_version, nr_local_addr* addrs, int addr_ct, nr_local_addr *addrp)
+ {
+ int r,_status;
+ nr_transport_addr default_addr;
+ int i;
+
+ if ((r=nr_ice_get_default_address(ctx, ip_version, &default_addr)))
+ ABORT(r);
+
+ for (i=0; i < addr_ct; ++i) {
+ if (!nr_transport_addr_cmp(&default_addr, &addrs[i].addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
+ if ((r=nr_local_addr_copy(addrp, &addrs[i])))
+ ABORT(r);
+ break;
+ }
+ }
+
+ if (i == addr_ct) {
+ if ((r=nr_transport_addr_copy(&addrp->addr, &default_addr)))
+ ABORT(r);
+ strlcpy(addrp->addr.ifname, "default route", sizeof(addrp->addr.ifname));
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_get_local_addresses(nr_ice_ctx *ctx)
+ {
+ int r,_status;
+ nr_local_addr local_addrs[MAXADDRS];
+ nr_local_addr *addrs = 0;
+ int i,addr_ct;
+ nr_local_addr default_addrs[2];
+ int default_addr_ct = 0;
+
+ if (!ctx->local_addrs) {
+ /* First, gather all the local addresses we have */
+ if((r=nr_stun_find_local_addresses(local_addrs,MAXADDRS,&addr_ct))) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to gather local addresses, trying default route",ctx->label);
+ }
+
+ if (ctx->force_net_interface[0] && addr_ct) {
+ /* Limit us to only addresses on a single interface */
+ int force_addr_ct = 0;
+ for(i=0;i<addr_ct;i++){
+ if (!strcmp(local_addrs[i].addr.ifname, ctx->force_net_interface)) {
+ // copy it down in the array, if needed
+ if (i != force_addr_ct) {
+ if (r=nr_local_addr_copy(&local_addrs[force_addr_ct], &local_addrs[i])) {
+ ABORT(r);
+ }
+ }
+ force_addr_ct++;
+ }
+ }
+ addr_ct = force_addr_ct;
+ }
+
+ if ((!addr_ct) || (ctx->flags & NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS)) {
+ /* Get just the default IPv4 and IPv6 addrs */
+ if(!nr_ice_get_default_local_address(ctx, NR_IPV4, local_addrs, addr_ct,
+ &default_addrs[default_addr_ct])) {
+ ++default_addr_ct;
+ }
+ if(!nr_ice_get_default_local_address(ctx, NR_IPV6, local_addrs, addr_ct,
+ &default_addrs[default_addr_ct])) {
+ ++default_addr_ct;
+ }
+ if (!default_addr_ct) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): failed to find default addresses",ctx->label);
+ ABORT(R_FAILED);
+ }
+ addrs = default_addrs;
+ addr_ct = default_addr_ct;
+ }
+ else {
+ addrs = local_addrs;
+ }
+
+ /* Sort interfaces by preference */
+ if(ctx->interface_prioritizer) {
+ for(i=0;i<addr_ct;i++){
+ if(r=nr_interface_prioritizer_add_interface(ctx->interface_prioritizer,addrs+i)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to add interface ",ctx->label);
+ ABORT(r);
+ }
+ }
+ if(r=nr_interface_prioritizer_sort_preference(ctx->interface_prioritizer)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): unable to sort interface by preference",ctx->label);
+ ABORT(r);
+ }
+ }
+
+ if (r=nr_ice_ctx_set_local_addrs(ctx,addrs,addr_ct)) {
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream;
+
+ if ((r=nr_ice_get_local_addresses(ctx)))
+ ABORT(r);
+
+ if(STAILQ_EMPTY(&ctx->streams)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): Missing streams to initialize",ctx->label);
+ ABORT(R_BAD_ARGS);
+ }
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Initializing candidates",ctx->label);
+ ctx->done_cb=done_cb;
+ ctx->cb_arg=cb_arg;
+
+ /* Initialize all the media stream/component pairs */
+ stream=STAILQ_FIRST(&ctx->streams);
+ while(stream){
+ if(r=nr_ice_media_stream_initialize(ctx,stream))
+ ABORT(r);
+
+ stream=STAILQ_NEXT(stream,entry);
+ }
+
+ if(ctx->uninitialized_candidates)
+ ABORT(R_WOULDBLOCK);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
+ {
+ int r,_status;
+
+ if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
+ ABORT(r);
+
+ STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp)
+ {
+ int r,_status;
+ nr_ice_peer_ctx *pctx;
+ nr_ice_media_stream *peer_stream;
+
+ pctx=STAILQ_FIRST(&ctx->peers);
+ while(pctx){
+ if(!nr_ice_peer_ctx_find_pstream(pctx, *streamp, &peer_stream)) {
+ if(r=nr_ice_peer_ctx_remove_pstream(pctx, &peer_stream)) {
+ ABORT(r);
+ }
+ }
+
+ pctx=STAILQ_NEXT(pctx,entry);
+ }
+
+ STAILQ_REMOVE(&ctx->streams,*streamp,nr_ice_media_stream_,entry);
+ if(r=nr_ice_media_stream_destroy(streamp)) {
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp)
+ {
+ char **attrs=0;
+ int _status;
+ char *tmp=0;
+
+ if(!(attrs=RCALLOC(sizeof(char *)*2)))
+ ABORT(R_NO_MEMORY);
+
+ if(!(tmp=RMALLOC(100)))
+ ABORT(R_NO_MEMORY);
+ snprintf(tmp,100,"ice-ufrag:%s",ctx->ufrag);
+ attrs[0]=tmp;
+
+ if(!(tmp=RMALLOC(100)))
+ ABORT(R_NO_MEMORY);
+ snprintf(tmp,100,"ice-pwd:%s",ctx->pwd);
+ attrs[1]=tmp;
+
+ *attrctp=2;
+ *attrsp=attrs;
+
+ _status=0;
+ abort:
+ if (_status){
+ if (attrs){
+ RFREE(attrs[0]);
+ RFREE(attrs[1]);
+ }
+ RFREE(attrs);
+ }
+ return(_status);
+ }
+
+static int nr_ice_random_string(char *str, int len)
+ {
+ unsigned char bytes[100];
+ int needed;
+ int r,_status;
+
+ if(len%2) ABORT(R_BAD_ARGS);
+ needed=len/2;
+
+ if(needed>sizeof(bytes)) ABORT(R_BAD_ARGS);
+
+ if(r=nr_crypto_random_bytes(bytes,needed))
+ ABORT(r);
+
+ if(r=nr_bin2hex(bytes,needed,(unsigned char *)str))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* This is incredibly annoying: we now have a datagram but we don't
+ know which peer it's from, and we need to be able to tell the
+ API user. So, offer it to each peer and if one bites, assume
+ the others don't want it
+*/
+int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
+ {
+ nr_ice_peer_ctx *pctx;
+ int r;
+
+ pctx=STAILQ_FIRST(&ctx->peers);
+ while(pctx){
+ r=nr_ice_peer_ctx_deliver_packet_maybe(pctx, comp, source_addr, data, len);
+ if(!r)
+ break;
+
+ pctx=STAILQ_NEXT(pctx,entry);
+ }
+
+ if(!pctx)
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Packet received from %s which doesn't match any known peer",ctx->label,source_addr->as_string);
+
+ return(0);
+ }
+
+int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12])
+ {
+ nr_ice_stun_id *xid;
+
+ xid=STAILQ_FIRST(&ctx->ids);
+ while(xid){
+ if (!memcmp(xid->id, id, 12))
+ return 1;
+
+ xid=STAILQ_NEXT(xid,entry);
+ }
+
+ return 0;
+ }
+
+int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg)
+{
+ int _status;
+ nr_ice_stun_id *xid;
+
+ xid = RCALLOC(sizeof(*xid));
+ if (!xid)
+ ABORT(R_NO_MEMORY);
+
+ assert(sizeof(xid->id) == sizeof(msg->header.id));
+#if __STDC_VERSION__ >= 201112L
+ _Static_assert(sizeof(xid->id) == sizeof(msg->header.id),"Message ID Size Mismatch");
+#endif
+ memcpy(xid->id, &msg->header.id, sizeof(xid->id));
+
+ STAILQ_INSERT_TAIL(&ctx->ids,xid,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+/* Clean up some of the resources (mostly file descriptors) used
+ by candidates we didn't choose. Note that this still leaves
+ a fair amount of non-system stuff floating around. This gets
+ cleaned up when you destroy the ICE ctx */
+int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx)
+ {
+ nr_ice_media_stream *lstr,*rstr;
+
+ r_log(LOG_ICE,LOG_DEBUG,"Finalizing ICE ctx %s, peer=%s",ctx->label,pctx->label);
+ /*
+ First find the peer stream, if any
+ */
+ lstr=STAILQ_FIRST(&ctx->streams);
+ while(lstr){
+ rstr=STAILQ_FIRST(&pctx->peer_streams);
+
+ while(rstr){
+ if(rstr->local_stream==lstr)
+ break;
+
+ rstr=STAILQ_NEXT(rstr,entry);
+ }
+
+ nr_ice_media_stream_finalize(lstr,rstr);
+
+ lstr=STAILQ_NEXT(lstr,entry);
+ }
+
+ return(0);
+ }
+
+
+int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
+{
+ ctx->trickle_cb = cb;
+ ctx->trickle_cb_arg = cb_arg;
+
+ return 0;
+}
+
+int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand)
+ {
+ if (cand->state != NR_ICE_CAND_STATE_INITIALIZED) {
+ return 1;
+ }
+
+ if (ctx->flags & NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES) {
+ if (cand->type == HOST)
+ return 1;
+ }
+
+ return 0;
+ }
+
+int nr_ice_get_new_ice_ufrag(char** ufrag)
+ {
+ int r,_status;
+ char buf[ICE_UFRAG_LEN+1];
+
+ if(r=nr_ice_random_string(buf,ICE_UFRAG_LEN))
+ ABORT(r);
+ if(!(*ufrag=r_strdup(buf)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if(_status) {
+ RFREE(*ufrag);
+ *ufrag = 0;
+ }
+ return(_status);
+ }
+
+int nr_ice_get_new_ice_pwd(char** pwd)
+ {
+ int r,_status;
+ char buf[ICE_PWD_LEN+1];
+
+ if(r=nr_ice_random_string(buf,ICE_PWD_LEN))
+ ABORT(r);
+ if(!(*pwd=r_strdup(buf)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if(_status) {
+ RFREE(*pwd);
+ *pwd = 0;
+ }
+ return(_status);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
new file mode 100644
index 000000000..cc79304f0
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h
@@ -0,0 +1,203 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_ctx_h
+#define _ice_ctx_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+/* Not good practice but making includes simpler */
+#include "transport_addr.h"
+#include "nr_socket.h"
+#include "nr_resolver.h"
+#include "nr_interface_prioritizer.h"
+#include "nr_socket_wrapper.h"
+#include "stun_client_ctx.h"
+#include "stun_server_ctx.h"
+#include "turn_client_ctx.h"
+
+#define NR_ICE_STUN_SERVER_TYPE_ADDR 1
+#define NR_ICE_STUN_SERVER_TYPE_DNSNAME 2
+
+typedef struct nr_ice_stun_server_ {
+ int type;
+ union {
+ nr_transport_addr addr;
+ struct {
+ char host[256]; /* Limit from RFC 1034, plus a 0 byte */
+ UINT2 port;
+ } dnsname;
+ } u;
+ int id;
+ int transport;
+} nr_ice_stun_server;
+
+typedef struct nr_ice_turn_server_ {
+ nr_ice_stun_server turn_server;
+ char *username;
+ Data *password;
+} nr_ice_turn_server;
+
+typedef struct nr_ice_foundation_ {
+ int index;
+
+ nr_transport_addr addr;
+ int type;
+ nr_ice_stun_server *stun_server;
+
+ STAILQ_ENTRY(nr_ice_foundation_) entry;
+} nr_ice_foundation;
+
+typedef STAILQ_HEAD(nr_ice_foundation_head_,nr_ice_foundation_) nr_ice_foundation_head;
+
+typedef TAILQ_HEAD(nr_ice_candidate_head_,nr_ice_candidate_) nr_ice_candidate_head;
+typedef TAILQ_HEAD(nr_ice_cand_pair_head_,nr_ice_cand_pair_) nr_ice_cand_pair_head;
+typedef struct nr_ice_component_ nr_ice_component;
+typedef struct nr_ice_media_stream_ nr_ice_media_stream;
+typedef struct nr_ice_ctx_ nr_ice_ctx;
+typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
+typedef struct nr_ice_candidate_ nr_ice_candidate;
+typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
+typedef void (*nr_ice_trickle_candidate_cb) (void *cb_arg,
+ nr_ice_ctx *ctx, nr_ice_media_stream *stream, int component_id,
+ nr_ice_candidate *candidate);
+
+#include "ice_socket.h"
+#include "ice_component.h"
+#include "ice_media_stream.h"
+#include "ice_candidate.h"
+#include "ice_candidate_pair.h"
+#include "ice_handler.h"
+#include "ice_peer_ctx.h"
+
+typedef struct nr_ice_stun_id_ {
+ UCHAR id[12];
+
+ STAILQ_ENTRY(nr_ice_stun_id_) entry;
+} nr_ice_stun_id;
+
+typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
+
+struct nr_ice_ctx_ {
+ UINT4 flags;
+ char *label;
+
+ char *ufrag;
+ char *pwd;
+
+ UINT4 Ta;
+
+ nr_ice_stun_server *stun_servers; /* The list of stun servers */
+ int stun_server_ct;
+ nr_ice_turn_server *turn_servers; /* The list of turn servers */
+ int turn_server_ct;
+ nr_local_addr *local_addrs; /* The list of available local addresses and corresponding interface information */
+ int local_addr_ct;
+
+ nr_resolver *resolver; /* The resolver to use */
+ nr_interface_prioritizer *interface_prioritizer; /* Priority decision logic */
+ nr_socket_wrapper_factory *turn_tcp_socket_wrapper; /* The TURN TCP socket wrapper to use */
+ nr_socket_factory *socket_factory;
+
+ nr_ice_foundation_head foundations;
+
+ nr_ice_media_stream_head streams; /* Media streams */
+ int stream_ct;
+ nr_ice_socket_head sockets; /* The sockets we're using */
+ int uninitialized_candidates;
+
+ UINT4 gather_rto;
+ UINT4 stun_delay;
+
+ UINT4 test_timer_divider;
+
+ nr_ice_peer_ctx_head peers;
+ nr_ice_stun_id_head ids;
+
+ NR_async_cb done_cb;
+ void *cb_arg;
+
+ nr_ice_trickle_candidate_cb trickle_cb;
+ void *trickle_cb_arg;
+
+ char force_net_interface[MAXIFNAME];
+};
+
+int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
+int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char* ufrag, char* pwd, nr_ice_ctx **ctxp);
+#define NR_ICE_CTX_FLAGS_OFFERER 1
+#define NR_ICE_CTX_FLAGS_ANSWERER (1<<1)
+#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
+#define NR_ICE_CTX_FLAGS_LITE (1<<3)
+#define NR_ICE_CTX_FLAGS_RELAY_ONLY (1<<4)
+#define NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES (1<<5)
+#define NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS (1<<6)
+#define NR_ICE_CTX_FLAGS_ONLY_PROXY (1<<7)
+
+void nr_ice_ctx_add_flags(nr_ice_ctx *ctx, UINT4 flags);
+void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags);
+int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
+int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
+int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
+void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg);
+int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
+int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp);
+int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp);
+int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
+int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
+int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
+int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
+int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers, int ct);
+int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct);
+int nr_ice_ctx_copy_turn_servers(nr_ice_ctx *ctx, nr_ice_turn_server *servers, int ct);
+int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver);
+int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *prioritizer);
+int nr_ice_ctx_set_turn_tcp_socket_wrapper(nr_ice_ctx *ctx, nr_socket_wrapper_factory *wrapper);
+void nr_ice_ctx_set_socket_factory(nr_ice_ctx *ctx, nr_socket_factory *factory);
+int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg);
+int nr_ice_ctx_hide_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
+int nr_ice_get_new_ice_ufrag(char** ufrag);
+int nr_ice_get_new_ice_pwd(char** pwd);
+
+#define NR_ICE_MAX_ATTRIBUTE_SIZE 256
+
+extern int LOG_ICE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_handler.h b/media/mtransport/third_party/nICEr/src/ice/ice_handler.h
new file mode 100644
index 000000000..5a0690ada
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_handler.h
@@ -0,0 +1,84 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_h
+#define _ice_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct nr_ice_handler_vtbl_ {
+ /* The checks on this media stream are done. The handler needs to
+ select a single pair to proceed with (regular nomination).
+ Once this returns the check starts and the pair can be
+ written on. Use nr_ice_candidate_pair_select() to perform the
+ selection.
+ TODO: !ekr! is this right?
+ */
+ int (*select_pair)(void *obj,nr_ice_media_stream *stream,
+int component_id, nr_ice_cand_pair **potentials,int potential_ct);
+
+ /* This media stream is ready to read/write (aggressive nomination).
+ May be called again if the nominated pair changes due to
+ ICE instability. TODO: !ekr! think about this
+ */
+ int (*stream_ready)(void *obj, nr_ice_media_stream *stream);
+
+ /* This media stream has failed */
+ int (*stream_failed)(void *obj, nr_ice_media_stream *stream);
+
+ /* ICE is connected for this peer ctx */
+ int (*ice_connected)(void *obj, nr_ice_peer_ctx *pctx);
+
+ /* A message was delivered to us */
+ int (*msg_recvd)(void *obj, nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, int component_id, UCHAR *msg, int len);
+
+ /* ICE has started checking. */
+ int (*ice_checking)(void *obj, nr_ice_peer_ctx *pctx);
+
+ /* ICE detected a (temporary?) disconnect. */
+ int (*ice_disconnected)(void *obj, nr_ice_peer_ctx *pctx);
+} nr_ice_handler_vtbl;
+
+typedef struct nr_ice_handler_ {
+ void *obj;
+ nr_ice_handler_vtbl *vtbl;
+} nr_ice_handler;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
new file mode 100644
index 000000000..b93e45aeb
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
@@ -0,0 +1,933 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <string.h>
+#include <assert.h>
+#include <nr_api.h>
+#include <r_assoc.h>
+#include <async_timer.h>
+#include "ice_util.h"
+#include "ice_ctx.h"
+
+static char *nr_ice_media_stream_states[]={"INVALID",
+ "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
+};
+
+int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
+
+int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream=0;
+ nr_ice_component *comp=0;
+ int i;
+
+ if(!(stream=RCALLOC(sizeof(nr_ice_media_stream))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(stream->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ stream->ctx=ctx;
+
+ STAILQ_INIT(&stream->components);
+ for(i=0;i<components;i++){
+ /* component-id must be > 0, so increment by 1 */
+ if(r=nr_ice_component_create(stream, i+1, &comp))
+ ABORT(r);
+
+ }
+
+ TAILQ_INIT(&stream->check_list);
+ TAILQ_INIT(&stream->trigger_check_queue);
+
+ stream->component_ct=components;
+ stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
+ *streamp=stream;
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_ice_media_stream_destroy(&stream);
+ }
+ return(_status);
+ }
+
+int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
+ {
+ nr_ice_media_stream *stream;
+ nr_ice_component *c1,*c2;
+ nr_ice_cand_pair *p1,*p2;
+ if(!streamp || !*streamp)
+ return(0);
+
+ stream=*streamp;
+ *streamp=0;
+
+ STAILQ_FOREACH_SAFE(c1, &stream->components, entry, c2){
+ STAILQ_REMOVE(&stream->components,c1,nr_ice_component_,entry);
+ nr_ice_component_destroy(&c1);
+ }
+
+ /* Note: all the entries from the trigger check queue are held in here as
+ * well, so we only clean up the super set. */
+ TAILQ_FOREACH_SAFE(p1, &stream->check_list, check_queue_entry, p2){
+ TAILQ_REMOVE(&stream->check_list,p1,check_queue_entry);
+ nr_ice_candidate_pair_destroy(&p1);
+ }
+
+ RFREE(stream->label);
+
+ RFREE(stream->ufrag);
+ RFREE(stream->pwd);
+ RFREE(stream->r2l_user);
+ RFREE(stream->l2r_user);
+ r_data_zfree(&stream->r2l_pass);
+ r_data_zfree(&stream->l2r_pass);
+
+ if(stream->timer)
+ NR_async_timer_cancel(stream->timer);
+
+ RFREE(stream);
+
+ return(0);
+ }
+
+int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if(r=nr_ice_component_initialize(ctx,comp))
+ ABORT(r);
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
+ {
+ int attrct=0;
+ nr_ice_component *comp;
+ char **attrs=0;
+ int index=0;
+ nr_ice_candidate *cand;
+ int r,_status;
+
+ *attrctp=0;
+
+ /* First find out how many attributes we need */
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if (comp->state != NR_ICE_COMPONENT_DISABLED) {
+ cand = TAILQ_FIRST(&comp->candidates);
+ while(cand){
+ if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
+ ++attrct;
+ }
+
+ cand = TAILQ_NEXT(cand, entry_comp);
+ }
+ }
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ if(attrct < 1){
+ r_log(LOG_ICE,LOG_ERR,"ICE-STREAM(%s): Failed to find any components for stream",stream->label);
+ ABORT(R_FAILED);
+ }
+
+ /* Make the array we'll need */
+ if(!(attrs=RCALLOC(sizeof(char *)*attrct)))
+ ABORT(R_NO_MEMORY);
+ for(index=0;index<attrct;index++){
+ if(!(attrs[index]=RMALLOC(NR_ICE_MAX_ATTRIBUTE_SIZE)))
+ ABORT(R_NO_MEMORY);
+ }
+
+ index=0;
+ /* Now format the attributes */
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if (comp->state != NR_ICE_COMPONENT_DISABLED) {
+ nr_ice_candidate *cand;
+
+ cand=TAILQ_FIRST(&comp->candidates);
+ while(cand){
+ if (!nr_ice_ctx_hide_candidate(stream->ctx, cand)) {
+ assert(index < attrct);
+
+ if (index >= attrct)
+ ABORT(R_INTERNAL);
+
+ if(r=nr_ice_format_candidate_attribute(cand, attrs[index],NR_ICE_MAX_ATTRIBUTE_SIZE))
+ ABORT(r);
+
+ index++;
+ }
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+ }
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ *attrsp=attrs;
+ *attrctp=attrct;
+
+ _status=0;
+ abort:
+ if(_status){
+ if(attrs){
+ for(index=0;index<attrct;index++){
+ RFREE(attrs[index]);
+ }
+ RFREE(attrs);
+ }
+ }
+ return(_status);
+ }
+
+/* Get a default candidate per 4.1.4 */
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if (comp->component_id == component)
+ break;
+
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ if (!comp)
+ ABORT(R_NOT_FOUND);
+
+ /* If there aren't any IPV4 candidates, try IPV6 */
+ if((r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV4)) &&
+ (r=nr_ice_component_get_default_candidate(comp, candp, NR_IPV6))) {
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
+ {
+ int r,_status;
+ nr_ice_component *pcomp,*lcomp;
+
+ pcomp=STAILQ_FIRST(&pstream->components);
+ lcomp=STAILQ_FIRST(&lstream->components);
+ while(pcomp){
+ if ((lcomp->state != NR_ICE_COMPONENT_DISABLED) &&
+ (pcomp->state != NR_ICE_COMPONENT_DISABLED)) {
+ if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
+ ABORT(r);
+ }
+
+ lcomp=STAILQ_NEXT(lcomp,entry);
+ pcomp=STAILQ_NEXT(pcomp,entry);
+ };
+
+ if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
+ nr_ice_media_stream_set_state(pstream, NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, nr_ice_media_stream *pstream, int *serviced)
+ {
+ nr_ice_component *pcomp;
+ int r,_status;
+ char *user = 0;
+
+ if (serviced)
+ *serviced = 0;
+
+ pcomp=STAILQ_FIRST(&pstream->components);
+ while(pcomp){
+ int serviced_inner=0;
+
+ /* Flush all the pre-answer requests */
+ if(r=nr_ice_component_service_pre_answer_requests(pctx, pcomp, pstream->r2l_user, &serviced_inner))
+ ABORT(r);
+ if (serviced)
+ *serviced += serviced_inner;
+
+ pcomp=STAILQ_NEXT(pcomp,entry);
+ }
+
+ _status=0;
+ abort:
+ RFREE(user);
+ return(_status);
+ }
+
+/* S 5.8 -- run the first pair from the triggered check queue (even after
+ * checks have completed S 8.1.2) or run the highest priority WAITING pair or
+ * if not available FROZEN pair from the check queue */
+static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream=cb_arg;
+ nr_ice_cand_pair *pair = 0;
+ int timer_multiplier=stream->pctx->active_streams ? stream->pctx->active_streams : 1;
+ int timer_val=stream->pctx->ctx->Ta*timer_multiplier;
+
+ assert(timer_val>0);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
+ stream->timer=0;
+
+ /* The trigger check queue has the highest priority */
+ pair=TAILQ_FIRST(&stream->trigger_check_queue);
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_WAITING){
+ /* Remove the pair from he trigger check queue */
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Removing pair from trigger check queue %s",stream->pctx->label,pair->as_string);
+ TAILQ_REMOVE(&stream->trigger_check_queue,pair,triggered_check_queue_entry);
+ break;
+ }
+ pair=TAILQ_NEXT(pair,triggered_check_queue_entry);
+ }
+
+ if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
+ if(!pair){
+ /* Find the highest priority WAITING check and move it to RUNNING */
+ pair=TAILQ_FIRST(&stream->check_list);
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_WAITING)
+ break;
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+ }
+
+ /* Hmmm... No WAITING. Let's look for FROZEN */
+ if(!pair){
+ pair=TAILQ_FIRST(&stream->check_list);
+
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
+ if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
+ ABORT(r);
+ break;
+ }
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+ }
+ }
+
+ if(pair){
+ nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
+ NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
+ }
+ else {
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): no pairs for %s",stream->pctx->label,stream->label);
+ }
+
+ _status=0;
+ abort:
+ return;
+ }
+
+/* Start checks for this media stream (aka check list) */
+int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
+ {
+ int r,_status;
+
+ /* Don't start the check timer if the stream is failed */
+ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FAILED) {
+ assert(0);
+ ABORT(R_INTERNAL);
+ }
+
+ /* Even if the stream is completed already remote can still create a new
+ * triggered check request which needs to fire, but not change our stream
+ * state. */
+ if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
+ if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)) {
+ ABORT(r);
+ }
+ }
+
+ if (!stream->timer) {
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): Starting check timer for stream.",pctx->label,stream->label);
+ nr_ice_media_stream_check_timer_cb(0,0,stream);
+ }
+
+ nr_ice_peer_ctx_stream_started_checks(pctx, stream);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* Start checks for this media stream (aka check list) S 5.7 */
+int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
+ {
+ int r,_status;
+ r_assoc *assoc=0;
+ nr_ice_cand_pair *pair=0;
+
+ /* Already seen assoc */
+ if(r=r_assoc_create(&assoc,r_assoc_crc32_hash_compute,5))
+ ABORT(r);
+
+ /* S 5.7.4. Set the highest priority pairs in each foundation to WAITING */
+ pair=TAILQ_FIRST(&stream->check_list);
+ while(pair){
+ void *v;
+
+ if(r=r_assoc_fetch(assoc,pair->foundation,strlen(pair->foundation),&v)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ if(r=nr_ice_candidate_pair_unfreeze(pctx,pair))
+ ABORT(r);
+
+ if(r=r_assoc_insert(assoc,pair->foundation,strlen(pair->foundation),
+ 0,0,0,R_ASSOC_NEW))
+ ABORT(r);
+ }
+
+ /* Already exists... fall through */
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ _status=0;
+ abort:
+ r_assoc_destroy(&assoc);
+ return(_status);
+ }
+
+static int nr_ice_media_stream_unfreeze_pairs_match(nr_ice_media_stream *stream, char *foundation)
+ {
+ nr_ice_cand_pair *pair;
+ int r,_status;
+ int unfroze=0;
+
+ pair=TAILQ_FIRST(&stream->check_list);
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_FROZEN &&
+ !strcmp(foundation,pair->foundation)){
+ if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
+ ABORT(r);
+ unfroze++;
+ }
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ if(!unfroze)
+ return(R_NOT_FOUND);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* S 7.1.2.2 */
+int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation)
+ {
+ int r,_status;
+ nr_ice_media_stream *str;
+ nr_ice_component *comp;
+ int invalid_comps=0;
+
+ /* 1. Unfreeze all frozen pairs with the same foundation
+ in this stream */
+ if(r=nr_ice_media_stream_unfreeze_pairs_match(stream,foundation)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ /* 2. See if there is a pair in the valid list for every component */
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if(!comp->valid_pairs)
+ invalid_comps++;
+
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ /* If there is a pair in the valid list for every component... */
+ /* Now go through the check lists for the other streams */
+ str=STAILQ_FIRST(&stream->pctx->peer_streams);
+ while(str){
+ if(str!=stream){
+ switch(str->ice_state){
+ case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
+ /* Unfreeze matching pairs */
+ if(r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation)){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ }
+ break;
+ case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
+ /* Unfreeze matching pairs if any */
+ r=nr_ice_media_stream_unfreeze_pairs_match(str,foundation);
+ if(r){
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+
+ /* OK, no matching pairs: execute the algorithm from 5.7
+ for this stream */
+ if(r=nr_ice_media_stream_unfreeze_pairs(str->pctx,str))
+ ABORT(r);
+ }
+ if(r=nr_ice_media_stream_start_checks(str->pctx,str))
+ ABORT(r);
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ str=STAILQ_NEXT(str,entry);
+ }
+
+/* nr_ice_media_stream_dump_state(stream->pctx,stream,stderr); */
+
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out)
+ {
+ nr_ice_cand_pair *pair;
+
+ /* r_log(LOG_ICE,LOG_DEBUG,"MEDIA-STREAM(%s): state dump", stream->label); */
+ pair=TAILQ_FIRST(&stream->check_list);
+ while(pair){
+ nr_ice_candidate_pair_dump_state(pair,out);
+
+ pair=TAILQ_NEXT(pair,check_queue_entry);
+ }
+
+ return(0);
+ }
+
+int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state)
+ {
+ /* Make no-change a no-op */
+ if (state == str->ice_state)
+ return 0;
+
+ assert(state < sizeof(nr_ice_media_stream_states)/sizeof(char *));
+ assert(str->ice_state < sizeof(nr_ice_media_stream_states)/sizeof(char *));
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): stream %s state %s->%s",
+ str->pctx->label,str->label,
+ nr_ice_media_stream_states[str->ice_state],
+ nr_ice_media_stream_states[state]);
+
+ if(state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)
+ str->pctx->active_streams++;
+ if(str->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)
+ str->pctx->active_streams--;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): %d active streams",
+ str->pctx->label, str->pctx->active_streams);
+
+ str->ice_state=state;
+
+ return(0);
+ }
+
+/* S OK, this component has a nominated. If every component has a nominated,
+ the stream is ready */
+int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
+ (comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
+ !comp->nominated)
+ break;
+
+ comp=STAILQ_NEXT(comp,entry);
+ }
+
+ /* At least one un-nominated component */
+ if(comp)
+ goto done;
+
+ /* All done... */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all active components have nominated candidate pairs",stream->pctx->label,stream->label);
+ nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
+
+ /* Cancel our timer */
+ if(stream->timer){
+ NR_async_timer_cancel(stream->timer);
+ stream->timer=0;
+ }
+
+ if (stream->pctx->handler) {
+ stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
+ }
+
+ /* Now tell the peer_ctx that we're connected */
+ if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx))
+ ABORT(r);
+
+ done:
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component)
+ {
+ int r,_status;
+ nr_ice_cand_pair *p2;
+
+ component->state=NR_ICE_COMPONENT_FAILED;
+
+ /* at least one component failed in this media stream, so the entire
+ * media stream is marked failed */
+
+ nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_FAILED);
+
+ /* OK, we need to cancel off everything on this component */
+ p2=TAILQ_FIRST(&stream->check_list);
+ while(p2){
+ if(r=nr_ice_candidate_pair_cancel(p2->pctx,p2,0))
+ ABORT(r);
+
+ p2=TAILQ_NEXT(p2,check_queue_entry);
+ }
+
+ /* Cancel our timer */
+ if(stream->timer){
+ NR_async_timer_cancel(stream->timer);
+ stream->timer=0;
+ }
+
+ if (stream->pctx->handler) {
+ stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
+ }
+
+ /* Now tell the peer_ctx that we're connected */
+ if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp)
+ {
+ nr_ice_candidate *cand;
+ nr_ice_candidate *best_cand=0;
+ nr_ice_component *comp;
+ int r,_status;
+
+ if(r=nr_ice_media_stream_find_component(str,component,&comp))
+ ABORT(r);
+
+ cand=TAILQ_FIRST(&comp->candidates);
+ while(cand){
+ if(cand->state==NR_ICE_CAND_STATE_INITIALIZED){
+ if(!best_cand || (cand->priority>best_cand->priority))
+ best_cand=cand;
+
+ }
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ if(!best_cand)
+ ABORT(R_NOT_FOUND);
+
+ *candp=best_cand;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+/* OK, we have the stream the user created, but that reflects the base
+ ICE ctx, not the peer_ctx. So, find the related stream in the pctx,
+ and then find the component */
+int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp)
+ {
+ int _status;
+ nr_ice_component *comp;
+
+ comp=STAILQ_FIRST(&str->components);
+ while(comp){
+ if(comp->component_id==comp_id)
+ break;
+
+ comp=STAILQ_NEXT(comp,entry);
+ }
+ if(!comp)
+ ABORT(R_NOT_FOUND);
+
+ *compp=comp;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ /* First find the peer component */
+ if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
+ ABORT(r);
+
+ /* Do we have an active pair yet? We should... */
+ if(!comp->active)
+ ABORT(R_NOT_FOUND);
+
+ /* Does fresh ICE consent exist? */
+ if(!comp->can_send)
+ ABORT(R_FAILED);
+
+ /* OK, write to that pair, which means:
+ 1. Use the socket on our local side.
+ 2. Use the address on the remote side
+ */
+ if(r=nr_socket_sendto(comp->active->local->osock,data,len,0,
+ &comp->active->remote->addr))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* Returns R_REJECTED if the component is unpaired or has been disabled. */
+int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ /* First find the peer component */
+ if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
+ ABORT(r);
+
+ if (comp->state == NR_ICE_COMPONENT_UNPAIRED ||
+ comp->state == NR_ICE_COMPONENT_DISABLED)
+ ABORT(R_REJECTED);
+
+ if(!comp->active)
+ ABORT(R_NOT_FOUND);
+
+ if (local) *local = comp->active->local;
+ if (remote) *remote = comp->active->remote;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ /* First find the peer component */
+ if(r=nr_ice_peer_ctx_find_component(pctx, str, component, &comp))
+ ABORT(r);
+
+ /* Do we have an active pair yet? We should... */
+ if(!comp->active)
+ ABORT(R_BAD_ARGS);
+
+ /* Use the socket on our local side */
+ if(r=nr_socket_getaddr(comp->active->local->osock,local))
+ ABORT(r);
+
+ /* Use the address on the remote side */
+ if(r=nr_transport_addr_copy(remote,&comp->active->remote->addr))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+
+int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr)
+ {
+ nr_ice_component *lcomp,*rcomp;
+
+ r_log(LOG_ICE,LOG_DEBUG,"Finalizing media stream %s, peer=%s",lstr->label,
+ rstr?rstr->label:"NONE");
+
+ lcomp=STAILQ_FIRST(&lstr->components);
+ if(rstr)
+ rcomp=STAILQ_FIRST(&rstr->components);
+ else
+ rcomp=0;
+
+ while(lcomp){
+ nr_ice_component_finalize(lcomp,rcomp);
+
+ lcomp=STAILQ_NEXT(lcomp,entry);
+ if(rcomp){
+ rcomp=STAILQ_NEXT(rcomp,entry);
+ }
+ }
+
+ return(0);
+ }
+
+int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ if ((r=nr_ice_media_stream_find_component(pstream, cand->component_id, &comp)))
+ ABORT(R_NOT_FOUND);
+
+ if (r=nr_ice_component_pair_candidate(pctx, comp, cand, 1))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_get_consent_status(nr_ice_media_stream *stream, int
+component_id, int *can_send, struct timeval *ts)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
+ ABORT(r);
+
+ *can_send = comp->can_send;
+ ts->tv_sec = comp->consent_last_seen.tv_sec;
+ ts->tv_usec = comp->consent_last_seen.tv_usec;
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
+ {
+ int r,_status;
+ nr_ice_component *comp;
+
+ if (stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)
+ ABORT(R_FAILED);
+
+ if ((r=nr_ice_media_stream_find_component(stream, component_id, &comp)))
+ ABORT(r);
+
+ /* Can only disable before pairing */
+ if (comp->state != NR_ICE_COMPONENT_UNPAIRED &&
+ comp->state != NR_ICE_COMPONENT_DISABLED)
+ ABORT(R_FAILED);
+
+ comp->state = NR_ICE_COMPONENT_DISABLED;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+void nr_ice_media_stream_role_change(nr_ice_media_stream *stream)
+ {
+ nr_ice_cand_pair *pair,*temp_pair;
+ /* Changing role causes candidate pair priority to change, which requires
+ * re-sorting the check list. */
+ nr_ice_cand_pair_head old_checklist;
+
+ assert(stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED);
+
+ /* Move check_list to old_checklist (not POD, have to do the hard way) */
+ TAILQ_INIT(&old_checklist);
+ TAILQ_FOREACH_SAFE(pair,&stream->check_list,check_queue_entry,temp_pair) {
+ TAILQ_REMOVE(&stream->check_list,pair,check_queue_entry);
+ TAILQ_INSERT_TAIL(&old_checklist,pair,check_queue_entry);
+ }
+
+ /* Re-insert into the check list */
+ TAILQ_FOREACH_SAFE(pair,&old_checklist,check_queue_entry,temp_pair) {
+ TAILQ_REMOVE(&old_checklist,pair,check_queue_entry);
+ nr_ice_candidate_pair_role_change(pair);
+ nr_ice_candidate_pair_insert(&stream->check_list,pair);
+ }
+ }
+
+int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *lcand, nr_ice_candidate *rcand, nr_ice_cand_pair **pair)
+ {
+ nr_ice_cand_pair_head *head = &str->check_list;
+ nr_ice_cand_pair *c1;
+
+ c1=TAILQ_FIRST(head);
+ while(c1){
+ if(c1->local == lcand &&
+ c1->remote == rcand) {
+ *pair=c1;
+ return(0);
+ }
+
+ c1=TAILQ_NEXT(c1,check_queue_entry);
+ }
+
+ return(R_NOT_FOUND);
+ }
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h
new file mode 100644
index 000000000..3d818d530
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h
@@ -0,0 +1,108 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_media_stream_h
+#define _ice_media_stream_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+struct nr_ice_media_stream_ {
+ char *label;
+ struct nr_ice_ctx_ *ctx;
+ struct nr_ice_peer_ctx_ *pctx;
+
+ struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
+ int component_ct;
+ nr_ice_component_head components;
+
+ char *ufrag; /* ICE username */
+ char *pwd; /* ICE password */
+ char *r2l_user; /* The username for incoming requests */
+ char *l2r_user; /* The username for outgoing requests */
+ Data r2l_pass; /* The password for incoming requests */
+ Data l2r_pass; /* The password for outcoming requests */
+ int ice_state;
+
+#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
+#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
+#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 3
+#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 4
+#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
+
+ nr_ice_cand_pair_head check_list;
+ nr_ice_cand_pair_head trigger_check_queue;
+ void *timer; /* Check list periodic timer */
+
+/* nr_ice_cand_pair_head valid_list; */
+
+ STAILQ_ENTRY(nr_ice_media_stream_) entry;
+};
+
+typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
+
+int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp);
+int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp);
+int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr);
+int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream);
+int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp,int *attrctp);
+int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
+int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
+int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream, int *serviced);
+int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
+int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
+int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
+int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
+int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
+int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
+int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len);
+int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote);
+int nr_ice_media_stream_find_component(nr_ice_media_stream *str, int comp_id, nr_ice_component **compp);
+int nr_ice_media_stream_find_pair(nr_ice_media_stream *str, nr_ice_candidate *local, nr_ice_candidate *remote, nr_ice_cand_pair **pair);
+int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_transport_addr *local, nr_transport_addr *remote);
+int
+nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);
+int nr_ice_media_stream_get_consent_status(nr_ice_media_stream *stream, int component_id, int *can_send, struct timeval *ts);
+int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id);
+int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand);
+void nr_ice_media_stream_role_change(nr_ice_media_stream *stream);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_parser.c b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c
new file mode 100644
index 000000000..7ec2bec5b
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c
@@ -0,0 +1,575 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <csi_platform.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <strings.h>
+#endif
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "nr_api.h"
+#include "ice_ctx.h"
+#include "ice_candidate.h"
+#include "ice_reg.h"
+
+static void
+skip_whitespace(char **str)
+{
+ char *c = *str;
+ while (*c == ' ')
+ ++c;
+
+ *str = c;
+}
+
+static void
+fast_forward(char **str, int skip)
+{
+ char *c = *str;
+ while (*c != '\0' && skip-- > 0)
+ ++c;
+
+ *str = c;
+}
+
+static void
+skip_to_past_space(char **str)
+{
+ char *c = *str;
+ while (*c != ' ' && *c != '\0')
+ ++c;
+
+ *str = c;
+
+ skip_whitespace(str);
+}
+
+static int
+grab_token(char **str, char **out)
+{
+ int _status;
+ char *c = *str;
+ int len;
+ char *tmp;
+
+ while (*c != ' ' && *c != '\0')
+ ++c;
+
+ len = c - *str;
+
+ tmp = RMALLOC(len + 1);
+ if (!tmp)
+ ABORT(R_NO_MEMORY);
+
+ memcpy(tmp, *str, len);
+ tmp[len] = '\0';
+
+ *str = c;
+ *out = tmp;
+
+ _status = 0;
+abort:
+ return _status;
+}
+
+int
+nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_stream *stream,nr_ice_candidate **candp)
+{
+ int r,_status;
+ char* str = orig;
+ nr_ice_candidate *cand;
+ char *connection_address=0;
+ unsigned int port;
+ int i;
+ unsigned int component_id;
+ char *rel_addr=0;
+ unsigned char transport;
+
+ if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(cand->label=r_strdup(orig)))
+ ABORT(R_NO_MEMORY);
+
+ cand->ctx=ctx;
+ cand->isock=0;
+ cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
+ cand->stream=stream;
+ skip_whitespace(&str);
+
+ /* Skip a= if present */
+ if (!strncmp(str, "a=", 2))
+ str += 2;
+
+ /* Candidate attr */
+ if (strncasecmp(str, "candidate:", 10))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 10);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* Foundation */
+ if ((r=grab_token(&str, &cand->foundation)))
+ ABORT(r);
+
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* component */
+ if (sscanf(str, "%u", &component_id) != 1)
+ ABORT(R_BAD_DATA);
+
+ if (component_id < 1 || component_id > 256)
+ ABORT(R_BAD_DATA);
+
+ cand->component_id = (UCHAR)component_id;
+
+ skip_to_past_space(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* Protocol */
+ if (!strncasecmp(str, "UDP", 3))
+ transport=IPPROTO_UDP;
+ else if (!strncasecmp(str, "TCP", 3))
+ transport=IPPROTO_TCP;
+ else
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 3);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* priority */
+ if (sscanf(str, "%u", &cand->priority) != 1)
+ ABORT(R_BAD_DATA);
+
+ if (cand->priority < 1)
+ ABORT(R_BAD_DATA);
+
+ skip_to_past_space(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* Peer address/port */
+ if ((r=grab_token(&str, &connection_address)))
+ ABORT(r);
+
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if (sscanf(str, "%u", &port) != 1)
+ ABORT(R_BAD_DATA);
+
+ if (port < 1 || port > 0x0FFFF)
+ ABORT(R_BAD_DATA);
+
+ if ((r=nr_str_port_to_transport_addr(connection_address,port,transport,&cand->addr)))
+ ABORT(r);
+
+ skip_to_past_space(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ /* Type */
+ if (strncasecmp("typ", str, 3))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 3);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ assert(nr_ice_candidate_type_names[0] == 0);
+
+ for (i = 1; nr_ice_candidate_type_names[i]; ++i) {
+ if(!strncasecmp(nr_ice_candidate_type_names[i], str, strlen(nr_ice_candidate_type_names[i]))) {
+ cand->type=i;
+ break;
+ }
+ }
+ if (nr_ice_candidate_type_names[i] == 0)
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, strlen(nr_ice_candidate_type_names[i]));
+
+ /* Look for the other side's raddr, rport */
+ /* raddr, rport */
+ switch (cand->type) {
+ case HOST:
+ break;
+ case SERVER_REFLEXIVE:
+ case PEER_REFLEXIVE:
+ case RELAYED:
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if (strncasecmp("raddr", str, 5))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 5);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if ((r=grab_token(&str, &rel_addr)))
+ ABORT(r);
+
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if (strncasecmp("rport", str, 5))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 5);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if (sscanf(str, "%u", &port) != 1)
+ ABORT(R_BAD_DATA);
+
+ if (port > 0x0FFFF)
+ ABORT(R_BAD_DATA);
+
+ if ((r=nr_str_port_to_transport_addr(rel_addr,port,transport,&cand->base)))
+ ABORT(r);
+
+ skip_to_past_space(&str);
+ /* it's expected to be at EOD at this point */
+
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ skip_whitespace(&str);
+
+ if (transport == IPPROTO_TCP && cand->type != RELAYED) {
+ /* Parse tcptype extension per RFC 6544 S 4.5 */
+ if (strncasecmp("tcptype ", str, 8))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 8);
+ skip_whitespace(&str);
+
+ for (i = 1; nr_ice_candidate_tcp_type_names[i]; ++i) {
+ if(!strncasecmp(nr_ice_candidate_tcp_type_names[i], str, strlen(nr_ice_candidate_tcp_type_names[i]))) {
+ cand->tcp_type=i;
+ fast_forward(&str, strlen(nr_ice_candidate_tcp_type_names[i]));
+ break;
+ }
+ }
+
+ if (cand->tcp_type == 0)
+ ABORT(R_BAD_DATA);
+
+ if (*str && *str != ' ')
+ ABORT(R_BAD_DATA);
+ }
+ /* Ignore extensions per RFC 5245 S 15.1 */
+#if 0
+ /* This used to be an assert, but we don't want to exit on invalid
+ remote data */
+ if (strlen(str) != 0) {
+ ABORT(R_BAD_DATA);
+ }
+#endif
+
+ nr_ice_candidate_compute_codeword(cand);
+
+ *candp=cand;
+
+ _status=0;
+ abort:
+ if (_status){
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
+ nr_ice_candidate_destroy(&cand);
+ }
+
+ RFREE(connection_address);
+ RFREE(rel_addr);
+ return(_status);
+}
+
+
+int
+nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr)
+{
+ int r,_status;
+ char *orig = 0;
+ char *str;
+
+ orig = str = attr;
+
+ if (!strncasecmp(str, "ice-ufrag:", 10)) {
+ fast_forward(&str, 10);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if ((r=grab_token(&str, &stream->ufrag)))
+ ABORT(r);
+ }
+ else if (!strncasecmp(str, "ice-pwd:", 8)) {
+ fast_forward(&str, 8);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if ((r=grab_token(&str, &stream->pwd)))
+ ABORT(r);
+ }
+ else {
+ ABORT(R_BAD_DATA);
+ }
+
+ skip_whitespace(&str);
+
+ /* RFC 5245 grammar doesn't have an extension point for ice-pwd or
+ ice-ufrag: if there's anything left on the line, we treat it as bad. */
+ if (str[0] != '\0') {
+ ABORT(R_BAD_DATA);
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (orig)
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
+ }
+
+ return(_status);
+}
+
+int
+nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct)
+{
+ int r,_status;
+ int i;
+ char *orig = 0;
+ char *str;
+ char *component_id = 0;
+ char *connection_address = 0;
+ unsigned int port;
+ in_addr_t addr;
+ char *ice_option_tag = 0;
+
+ for(i=0;i<attr_ct;i++){
+ orig = str = attrs[i];
+
+ component_id = 0;
+ connection_address = 0;
+ ice_option_tag = 0;
+
+ if (!strncasecmp(str, "remote-candidates:", 18)) {
+ fast_forward(&str, 18);
+ skip_whitespace(&str);
+
+ while (*str != '\0') {
+ if ((r=grab_token(&str, &component_id)))
+ ABORT(r);
+
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if ((r=grab_token(&str, &connection_address)))
+ ABORT(r);
+
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ addr = inet_addr(connection_address);
+ if (addr == INADDR_NONE)
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ if (sscanf(str, "%u", &port) != 1)
+ ABORT(R_BAD_DATA);
+
+ if (port < 1 || port > 0x0FFFF)
+ ABORT(R_BAD_DATA);
+
+ skip_to_past_space(&str);
+
+#if 0
+ /* TODO: !nn! just drop on the floor for now, later put somewhere */
+ /* Assume v4 for now */
+ if(r=nr_ip4_port_to_transport_addr(ntohl(addr),port,IPPROTO_UDP,&candidate->base))
+ ABORT(r);
+
+ TAILQ_INSERT_TAIL(head, elm, field);
+#endif
+
+ component_id = 0; /* prevent free */
+ RFREE(connection_address);
+ connection_address = 0; /* prevent free */
+ }
+ }
+ else if (!strncasecmp(str, "ice-lite", 8)) {
+ pctx->peer_lite = 1;
+
+ fast_forward(&str, 8);
+ }
+ else if (!strncasecmp(str, "ice-mismatch", 12)) {
+ pctx->peer_ice_mismatch = 1;
+
+ fast_forward(&str, 12);
+ }
+ else if (!strncasecmp(str, "ice-ufrag:", 10)) {
+ fast_forward(&str, 10);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ RFREE(pctx->peer_ufrag);
+ pctx->peer_ufrag = 0;
+ if ((r=grab_token(&str, &pctx->peer_ufrag)))
+ ABORT(r);
+ }
+ else if (!strncasecmp(str, "ice-pwd:", 8)) {
+ fast_forward(&str, 8);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ skip_whitespace(&str);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+
+ RFREE(pctx->peer_pwd);
+ pctx->peer_pwd = 0;
+ if ((r=grab_token(&str, &pctx->peer_pwd)))
+ ABORT(r);
+ }
+ else if (!strncasecmp(str, "ice-options:", 12)) {
+ fast_forward(&str, 12);
+ skip_whitespace(&str);
+
+ while (*str != '\0') {
+ if ((r=grab_token(&str, &ice_option_tag)))
+ ABORT(r);
+
+ skip_whitespace(&str);
+
+ //TODO: for now, just throw away; later put somewhere
+ RFREE(ice_option_tag);
+
+ ice_option_tag = 0; /* prevent free */
+ }
+ }
+ else {
+ ABORT(R_BAD_DATA);
+ }
+
+ skip_whitespace(&str);
+
+ /* RFC 5245 grammar doesn't have an extension point for any of the
+ preceding attributes: if there's anything left on the line, we
+ treat it as bad data. */
+ if (str[0] != '\0') {
+ ABORT(R_BAD_DATA);
+ }
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (orig)
+ r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s): Error parsing attribute: %s",pctx->label,orig);
+ }
+
+ RFREE(connection_address);
+ RFREE(component_id);
+ RFREE(ice_option_tag);
+ return(_status);
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c
new file mode 100644
index 000000000..d494e45de
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c
@@ -0,0 +1,825 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <string.h>
+#include <assert.h>
+#include <registry.h>
+#include <nr_api.h>
+#include "ice_ctx.h"
+#include "ice_peer_ctx.h"
+#include "ice_media_stream.h"
+#include "ice_util.h"
+#include "nr_crypto.h"
+#include "async_timer.h"
+#include "ice_reg.h"
+
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
+static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct);
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate);
+
+int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
+ {
+ int r,_status;
+ nr_ice_peer_ctx *pctx=0;
+
+ if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ pctx->state = NR_ICE_PEER_STATE_UNPAIRED;
+
+ if(!(pctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ pctx->ctx=ctx;
+ pctx->handler=handler;
+
+ /* Decide controlling vs. controlled */
+ if(ctx->flags & NR_ICE_CTX_FLAGS_LITE){
+ pctx->controlling=0;
+ }
+ else{
+ if(ctx->flags & NR_ICE_CTX_FLAGS_OFFERER)
+ pctx->controlling=1;
+ else if(ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER)
+ pctx->controlling=0;
+ }
+ if(r=nr_crypto_random_bytes((UCHAR *)&pctx->tiebreaker,8))
+ ABORT(r);
+
+ STAILQ_INIT(&pctx->peer_streams);
+
+ STAILQ_INSERT_TAIL(&ctx->peers,pctx,entry);
+
+ *pctxp=pctx;
+
+ _status = 0;
+ abort:
+ if(_status){
+ nr_ice_peer_ctx_destroy_cb(0,0,pctx);
+ }
+ return(_status);
+ }
+
+
+
+int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
+ {
+ nr_ice_media_stream *pstream=0;
+ nr_ice_component *comp,*comp2;
+ char *lufrag,*rufrag;
+ char *lpwd,*rpwd;
+ int r,_status;
+
+ /*
+ Note: use component_ct from our own stream since components other
+ than this offered by the other side are unusable */
+ if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream))
+ ABORT(r);
+
+ /* Match up the local and remote components */
+ comp=STAILQ_FIRST(&stream->components);
+ comp2=STAILQ_FIRST(&pstream->components);
+ while(comp){
+ comp2->local_component=comp;
+
+ comp=STAILQ_NEXT(comp,entry);
+ comp2=STAILQ_NEXT(comp2,entry);
+ }
+
+ pstream->local_stream=stream;
+ pstream->pctx=pctx;
+
+ if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
+ ABORT(r);
+
+ /* Now that we have the ufrag and password, compute all the username/password
+ pairs */
+ lufrag=stream->ufrag?stream->ufrag:pctx->ctx->ufrag;
+ lpwd=stream->pwd?stream->pwd:pctx->ctx->pwd;
+ assert(lufrag);
+ assert(lpwd);
+ rufrag=pstream->ufrag?pstream->ufrag:pctx->peer_ufrag;
+ rpwd=pstream->pwd?pstream->pwd:pctx->peer_pwd;
+ if (!rufrag || !rpwd)
+ ABORT(R_BAD_DATA);
+
+ if(r=nr_concat_strings(&pstream->r2l_user,lufrag,":",rufrag,NULL))
+ ABORT(r);
+ if(r=nr_concat_strings(&pstream->l2r_user,rufrag,":",lufrag,NULL))
+ ABORT(r);
+ if(r=r_data_make(&pstream->r2l_pass, (UCHAR *)lpwd, strlen(lpwd)))
+ ABORT(r);
+ if(r=r_data_make(&pstream->l2r_pass, (UCHAR *)rpwd, strlen(rpwd)))
+ ABORT(r);
+
+ STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct)
+ {
+ int r;
+ int i;
+
+ for(i=0;i<attr_ct;i++){
+ if(!strncmp(attrs[i],"ice-",4)){
+ if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
+ continue;
+ }
+ }
+ else if (!strncmp(attrs[i],"candidate",9)){
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i])) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
+ continue;
+ }
+ }
+ else {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) specified bogus attribute: %s",pctx->ctx->label,pctx->label,attrs[i]);
+ }
+ }
+
+ /* Doesn't fail because we just skip errors */
+ return(0);
+ }
+
+static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate)
+ {
+ nr_ice_candidate *cand=0;
+ nr_ice_component *comp;
+ int j;
+ int r, _status;
+
+ if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
+ ABORT(r);
+ if(cand->component_id-1>=pstream->component_ct){
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
+ ABORT(R_BAD_DATA);
+ }
+
+ /* Not the fastest way to find a component, but it's what we got */
+ j=1;
+ for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
+ if(j==cand->component_id)
+ break;
+
+ j++;
+ }
+
+ if(!comp){
+ r_log(LOG_ICE,LOG_WARNING,"Peer answered with more components than we offered");
+ ABORT(R_BAD_DATA);
+ }
+
+ if (comp->state == NR_ICE_COMPONENT_DISABLED) {
+ r_log(LOG_ICE,LOG_WARNING,"Peer offered candidates for disabled remote component");
+ ABORT(R_BAD_DATA);
+ }
+ if (comp->local_component->state == NR_ICE_COMPONENT_DISABLED) {
+ r_log(LOG_ICE,LOG_WARNING,"Peer offered candidates for disabled local component");
+ ABORT(R_BAD_DATA);
+ }
+
+ cand->component=comp;
+
+ TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND(%s): creating peer candidate",
+ pctx->label,cand->label);
+
+ _status=0;
+ abort:
+ if (_status) {
+ nr_ice_candidate_destroy(&cand);
+ }
+ return(_status);
+ }
+
+int nr_ice_peer_ctx_find_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream **pstreamp)
+ {
+ int _status;
+ nr_ice_media_stream *pstream;
+
+ /* Because we don't have forward pointers, iterate through all the
+ peer streams to find one that matches us */
+ pstream=STAILQ_FIRST(&pctx->peer_streams);
+ while(pstream) {
+ if (pstream->local_stream == stream)
+ break;
+
+ pstream = STAILQ_NEXT(pstream, entry);
+ }
+ if (!pstream) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ *pstreamp = pstream;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_peer_ctx_remove_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream **pstreamp)
+ {
+ int r,_status;
+
+ STAILQ_REMOVE(&pctx->peer_streams,*pstreamp,nr_ice_media_stream_,entry);
+
+ if(r=nr_ice_media_stream_destroy(pstreamp)) {
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
+ {
+ nr_ice_media_stream *pstream;
+ int r,_status;
+ int needs_pairing = 0;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): peer (%s) parsing trickle ICE candidate %s",pctx->ctx->label,pctx->label,candidate);
+ r = nr_ice_peer_ctx_find_pstream(pctx, stream, &pstream);
+ if (r)
+ ABORT(r);
+
+ switch(pstream->ice_state) {
+ case NR_ICE_MEDIA_STREAM_UNPAIRED:
+ break;
+ case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
+ case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
+ needs_pairing = 1;
+ break;
+ default:
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) tried to trickle ICE in inappropriate state %d",pctx->ctx->label,pctx->label,stream->label,pstream->ice_state);
+ ABORT(R_ALREADY);
+ break;
+ }
+
+ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
+ ABORT(r);
+ }
+
+ /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
+ then we need to pair this new candidate. For now we
+ just re-pair the stream which is inefficient but still
+ fine because we suppress duplicate pairing */
+ if (needs_pairing) {
+ if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
+ ABORT(r);
+ }
+
+ /* Start checks if this stream is not checking yet or if it has checked
+ all the available candidates but not had a completed check for all
+ components.
+
+ Note that this is not compliant with RFC 5245, but consistent with
+ the libjingle trickle ICE behavior. Note that we will not restart
+ checks if either (a) the stream has failed or (b) all components
+ have a successful pair because the switch statement above jumps
+ will in both states.
+
+ TODO(ekr@rtfm.com): restart checks.
+ TODO(ekr@rtfm.com): update when the trickle ICE RFC is published
+ */
+ if (!pstream->timer) {
+ if(r=nr_ice_media_stream_start_checks(pctx, pstream)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to start checks",pctx->ctx->label,pctx->label,stream->label);
+ ABORT(r);
+ }
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+
+ }
+
+
+static void nr_ice_peer_ctx_trickle_wait_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_peer_ctx *pctx=cb_arg;
+ nr_ice_media_stream *stream;
+ nr_ice_component *comp;
+
+ pctx->trickle_grace_period_timer=0;
+
+ r_log(LOG_ICE,LOG_INFO,"ICE(%s): peer (%s) Trickle grace period is over; marking every component with only failed pairs as failed.",pctx->ctx->label,pctx->label);
+
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ while(stream){
+ comp=STAILQ_FIRST(&stream->components);
+ while(comp){
+ nr_ice_component_check_if_failed(comp);
+ comp=STAILQ_NEXT(comp,entry);
+ }
+ stream=STAILQ_NEXT(stream,entry);
+ }
+ }
+
+static void nr_ice_peer_ctx_start_trickle_timer(nr_ice_peer_ctx *pctx)
+ {
+ UINT4 grace_period_timeout=0;
+
+ if(pctx->trickle_grace_period_timer) {
+ NR_async_timer_cancel(pctx->trickle_grace_period_timer);
+ pctx->trickle_grace_period_timer=0;
+ }
+
+ NR_reg_get_uint4(NR_ICE_REG_TRICKLE_GRACE_PERIOD,&grace_period_timeout);
+
+ if (grace_period_timeout) {
+ /* If we're doing trickle, we need to allow a grace period for new
+ * trickle candidates to arrive in case the pairs we have fail quickly. */
+ NR_ASYNC_TIMER_SET(grace_period_timeout,nr_ice_peer_ctx_trickle_wait_cb,pctx,&pctx->trickle_grace_period_timer);
+ }
+ }
+
+int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
+ {
+ nr_ice_media_stream *stream;
+ int r,_status;
+
+ if(pctx->peer_lite && !pctx->controlling) {
+ if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_LITE){
+ r_log(LOG_ICE,LOG_ERR,"Both sides are ICE-Lite");
+ ABORT(R_BAD_DATA);
+ }
+ nr_ice_peer_ctx_switch_controlling_role(pctx);
+ }
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): peer (%s) pairing candidates",pctx->ctx->label,pctx->label);
+
+ if(STAILQ_EMPTY(&pctx->peer_streams)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attributes",pctx->ctx->label,pctx->label);
+ ABORT(R_FAILED);
+ }
+
+ /* Set this first; if we fail partway through, we do not want to end
+ * up in UNPAIRED after creating some pairs. */
+ pctx->state = NR_ICE_PEER_STATE_PAIRED;
+
+ /* Start grace period timer for incoming trickle candidates */
+ nr_ice_peer_ctx_start_trickle_timer(pctx);
+
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ while(stream){
+ if(r=nr_ice_media_stream_pair_candidates(pctx, stream->local_stream,
+ stream))
+ ABORT(r);
+
+ stream=STAILQ_NEXT(stream,entry);
+ }
+
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+int nr_ice_peer_ctx_pair_new_trickle_candidate(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx, nr_ice_candidate *cand)
+ {
+ int r, _status;
+ nr_ice_media_stream *pstream;
+
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) pairing local trickle ICE candidate %s",pctx->ctx->label,pctx->label,cand->label);
+ if ((r = nr_ice_peer_ctx_find_pstream(pctx, cand->stream, &pstream)))
+ ABORT(r);
+
+ if ((r = nr_ice_media_stream_pair_new_trickle_candidate(pctx, pstream, cand)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return _status;
+ }
+
+int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id)
+ {
+ int r, _status;
+ nr_ice_media_stream *pstream;
+ nr_ice_component *component;
+
+ if ((r=nr_ice_peer_ctx_find_pstream(pctx, lstream, &pstream)))
+ ABORT(r);
+
+ /* We shouldn't be calling this after we have started pairing */
+ if (pstream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED)
+ ABORT(R_FAILED);
+
+ if ((r=nr_ice_media_stream_find_component(pstream, component_id,
+ &component)))
+ ABORT(r);
+
+ component->state = NR_ICE_COMPONENT_DISABLED;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_peer_ctx *pctx=cb_arg;
+ nr_ice_media_stream *str1,*str2;
+
+ NR_async_timer_cancel(pctx->connected_cb_timer);
+ RFREE(pctx->label);
+ RFREE(pctx->peer_ufrag);
+ RFREE(pctx->peer_pwd);
+
+ STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){
+ STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry);
+ nr_ice_media_stream_destroy(&str1);
+ }
+ assert(pctx->ctx);
+ if (pctx->ctx)
+ STAILQ_REMOVE(&pctx->ctx->peers, pctx, nr_ice_peer_ctx_, entry);
+
+ if(pctx->trickle_grace_period_timer) {
+ NR_async_timer_cancel(pctx->trickle_grace_period_timer);
+ pctx->trickle_grace_period_timer=0;
+ }
+
+ RFREE(pctx);
+ }
+
+int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
+ {
+
+ if(!pctxp || !*pctxp)
+ return(0);
+
+ /* Stop calling the handler */
+ (*pctxp)->handler = 0;
+
+ NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
+
+ *pctxp=0;
+
+ return(0);
+ }
+
+
+/* Start the checks for the first media stream (S 5.7)
+ The rest remain FROZEN */
+int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
+ {
+ return nr_ice_peer_ctx_start_checks2(pctx, 0);
+ }
+
+/* Start checks for some media stream.
+
+ If allow_non_first == 0, then we only look at the first stream,
+ which is 5245-complaint.
+
+ If allow_non_first == 1 then we find the first non-empty stream
+ This is not compliant with RFC 5245 but is necessary to make trickle ICE
+ work plausibly
+*/
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream;
+ int started = 0;
+
+ /* Might have added some streams */
+ pctx->reported_connected = 0;
+ NR_async_timer_cancel(pctx->connected_cb_timer);
+ pctx->connected_cb_timer = 0;
+ pctx->checks_started = 0;
+
+ if((r=nr_ice_peer_ctx_check_if_connected(pctx))) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) initial connected check failed",pctx->ctx->label,pctx->label);
+ ABORT(r);
+ }
+
+ if (pctx->reported_connected) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) in %s all streams were done",pctx->ctx->label,pctx->label,__FUNCTION__);
+ return (0);
+ }
+
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ if(!stream)
+ ABORT(R_FAILED);
+
+ while (stream) {
+ assert(stream->ice_state != NR_ICE_MEDIA_STREAM_UNPAIRED);
+
+ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
+ if(!TAILQ_EMPTY(&stream->check_list))
+ break;
+
+ if(!allow_non_first){
+ /* This test applies if:
+
+ 1. allow_non_first is 0 (i.e., non-trickle ICE)
+ 2. the first stream has an empty check list.
+
+ But in the non-trickle ICE case, the other side should have provided
+ some candidates or ICE is pretty much not going to work and we're
+ just going to fail. Hence R_FAILED as opposed to R_NOT_FOUND and
+ immediate termination here.
+ */
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
+ ABORT(R_FAILED);
+ }
+ }
+
+ stream=STAILQ_NEXT(stream, entry);
+ }
+
+ if (!stream) {
+ /*
+ We fail above if we aren't doing trickle, and this is not all that
+ unusual in the trickle case.
+ */
+ r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
+ }
+ else if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
+ if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
+ ABORT(r);
+ if(r=nr_ice_media_stream_start_checks(pctx,stream))
+ ABORT(r);
+ ++started;
+ }
+
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ while (stream) {
+ int serviced = 0;
+ if (r=nr_ice_media_stream_service_pre_answer_requests(pctx, stream->local_stream, stream, &serviced))
+ ABORT(r);
+
+ if (serviced) {
+ ++started;
+ }
+ else {
+ r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no streams with pre-answer requests",pctx->ctx->label,pctx->label);
+ }
+
+
+ stream=STAILQ_NEXT(stream, entry);
+ }
+
+ if (!started) {
+ r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) no checks to start",pctx->ctx->label,pctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+void nr_ice_peer_ctx_stream_started_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
+ {
+ if (!pctx->checks_started) {
+ r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): peer (%s) is now checking",pctx->ctx->label,pctx->label);
+ pctx->checks_started = 1;
+ if (pctx->handler && pctx->handler->vtbl->ice_checking) {
+ pctx->handler->vtbl->ice_checking(pctx->handler->obj, pctx);
+ }
+ }
+ }
+
+#ifndef NDEBUG
+int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream;
+
+ fprintf(out,"PEER %s STATE DUMP\n",pctx->label);
+ fprintf(out,"==========================================\n");
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ while(stream){
+ if(r=nr_ice_media_stream_dump_state(pctx,stream,out))
+ ABORT(r);
+
+ stream=STAILQ_NEXT(stream,entry);
+ }
+ fprintf(out,"==========================================\n");
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+#endif
+
+void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx)
+ {
+ if (pctx->reported_connected &&
+ pctx->handler &&
+ pctx->handler->vtbl->ice_disconnected) {
+ pctx->handler->vtbl->ice_disconnected(pctx->handler->obj, pctx);
+ }
+ }
+
+void nr_ice_peer_ctx_connected(nr_ice_peer_ctx *pctx)
+ {
+ /* Fire the handler callback to say we're done */
+ if (pctx->reported_connected &&
+ pctx->handler &&
+ pctx->handler->vtbl->ice_connected) {
+ pctx->handler->vtbl->ice_connected(pctx->handler->obj, pctx);
+ }
+ }
+
+static void nr_ice_peer_ctx_fire_connected(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_peer_ctx *pctx=cb_arg;
+
+ pctx->connected_cb_timer=0;
+
+ nr_ice_peer_ctx_connected(pctx);
+ }
+
+/* Examine all the streams to see if we're
+ maybe miraculously connected */
+int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx)
+ {
+ int _status;
+ nr_ice_media_stream *str;
+ int failed=0;
+ int succeeded=0;
+
+ str=STAILQ_FIRST(&pctx->peer_streams);
+ while(str){
+ if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED){
+ succeeded++;
+ }
+ else if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FAILED){
+ failed++;
+ }
+ else{
+ break;
+ }
+ str=STAILQ_NEXT(str,entry);
+ }
+
+ if(str)
+ goto done; /* Something isn't done */
+
+ /* OK, we're finished, one way or another */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): all checks completed success=%d fail=%d",pctx->label,succeeded,failed);
+
+ /* Schedule a connected notification for the first connected event.
+ IMPORTANT: This is done in a callback because we expect destructors
+ of various kinds to be fired from here */
+ if (!pctx->reported_connected) {
+ pctx->reported_connected = 1;
+ assert(!pctx->connected_cb_timer);
+ NR_ASYNC_TIMER_SET(0,nr_ice_peer_ctx_fire_connected,pctx,&pctx->connected_cb_timer);
+ }
+
+ done:
+ _status=0;
+// abort:
+ return(_status);
+ }
+
+
+/* Given a component in the main ICE ctx, find the relevant component in
+ the peer_ctx */
+int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp)
+ {
+ nr_ice_media_stream *pstr;
+ int r,_status;
+
+ pstr=STAILQ_FIRST(&pctx->peer_streams);
+ while(pstr){
+ if(pstr->local_stream==str)
+ break;
+
+ pstr=STAILQ_NEXT(pstr,entry);
+ }
+ if(!pstr)
+ ABORT(R_BAD_ARGS);
+
+ if(r=nr_ice_media_stream_find_component(pstr,component_id,compp))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/*
+ This packet may be for us.
+
+ 1. Find the matching peer component
+ 2. Examine the packet source address to see if it matches
+ one of the peer candidates.
+ 3. Fire the relevant callback handler if there is a match
+
+ Return 0 if match, R_REJECTED if no match, other errors
+ if we can't even find the component or something like that.
+*/
+
+int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len)
+ {
+ nr_ice_component *peer_comp;
+ nr_ice_candidate *cand;
+ int r,_status;
+
+ if(r=nr_ice_peer_ctx_find_component(pctx, comp->stream, comp->component_id,
+ &peer_comp))
+ ABORT(r);
+
+ /* OK, we've found the component, now look for matches */
+ cand=TAILQ_FIRST(&peer_comp->candidates);
+ while(cand){
+ if(!nr_transport_addr_cmp(source_addr,&cand->addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ break;
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ if(!cand)
+ ABORT(R_REJECTED);
+
+ /* OK, there's a match. Call the handler */
+
+ if (pctx->handler) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
+
+ pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
+ pctx,comp->stream,comp->component_id,data,len);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+void nr_ice_peer_ctx_switch_controlling_role(nr_ice_peer_ctx *pctx)
+ {
+ int controlling = !(pctx->controlling);
+ if(pctx->controlling_conflict_resolved) {
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) %s called more than once; "
+ "this probably means the peer is confused. Not switching roles.",
+ pctx->ctx->label,pctx->label,__FUNCTION__);
+ return;
+ }
+
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): detected "
+ "role conflict. Switching to %s",
+ pctx->label,
+ controlling ? "controlling" : "controlled");
+
+ pctx->controlling = controlling;
+ pctx->controlling_conflict_resolved = 1;
+
+ if(pctx->state == NR_ICE_PEER_STATE_PAIRED) {
+ /* We have formed candidate pairs. We need to inform them. */
+ nr_ice_media_stream *pstream=STAILQ_FIRST(&pctx->peer_streams);
+ while(pstream) {
+ nr_ice_media_stream_role_change(pstream);
+ pstream = STAILQ_NEXT(pstream, entry);
+ }
+ }
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h
new file mode 100644
index 000000000..47e3be704
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h
@@ -0,0 +1,101 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_peer_ctx_h
+#define _ice_peer_ctx_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+struct nr_ice_peer_ctx_ {
+ int state;
+#define NR_ICE_PEER_STATE_UNPAIRED 1
+#define NR_ICE_PEER_STATE_PAIRED 2
+
+ char *label;
+ nr_ice_ctx *ctx;
+ nr_ice_handler *handler;
+
+ UCHAR controlling; /* 1 for controlling, 0 for controlled */
+ UCHAR controlling_conflict_resolved;
+ UINT8 tiebreaker;
+
+ char *peer_ufrag;
+ char *peer_pwd;
+ int peer_lite;
+ int peer_ice_mismatch;
+
+ nr_ice_media_stream_head peer_streams;
+ int active_streams;
+ int waiting_pairs;
+ UCHAR checks_started;
+
+ void *connected_cb_timer;
+ UCHAR reported_connected;
+ void *trickle_grace_period_timer;
+
+ STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
+};
+
+typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
+
+int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp);
+int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp);
+int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct);
+int nr_ice_peer_ctx_find_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream **pstreamp);
+int nr_ice_peer_ctx_remove_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream **pstreamp);
+int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *cand);
+
+int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct);
+int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
+void nr_ice_peer_ctx_stream_started_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx);
+void nr_ice_peer_ctx_connected(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out);
+int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx);
+int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
+int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
+int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id);
+int nr_ice_peer_ctx_pair_new_trickle_candidate(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx, nr_ice_candidate *cand);
+void nr_ice_peer_ctx_switch_controlling_role(nr_ice_peer_ctx *pctx);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_reg.h b/media/mtransport/third_party/nICEr/src/ice/ice_reg.h
new file mode 100644
index 000000000..dc0f74172
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_reg.h
@@ -0,0 +1,79 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_reg_h
+#define _ice_reg_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+#define NR_ICE_REG_PREF_TYPE_HOST "ice.pref.type.host"
+#define NR_ICE_REG_PREF_TYPE_RELAYED "ice.pref.type.relayed"
+#define NR_ICE_REG_PREF_TYPE_SRV_RFLX "ice.pref.type.srv_rflx"
+#define NR_ICE_REG_PREF_TYPE_PEER_RFLX "ice.pref.type.peer_rflx"
+#define NR_ICE_REG_PREF_TYPE_HOST_TCP "ice.pref.type.host_tcp"
+#define NR_ICE_REG_PREF_TYPE_RELAYED_TCP "ice.pref.type.relayed_tcp"
+#define NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP "ice.pref.type.srv_rflx_tcp"
+#define NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP "ice.pref.type.peer_rflx_tcp"
+
+#define NR_ICE_REG_PREF_INTERFACE_PRFX "ice.pref.interface"
+#define NR_ICE_REG_SUPPRESS_INTERFACE_PRFX "ice.suppress.interface"
+
+#define NR_ICE_REG_STUN_SRV_PRFX "ice.stun.server"
+#define NR_ICE_REG_STUN_SRV_ADDR "addr"
+#define NR_ICE_REG_STUN_SRV_PORT "port"
+
+#define NR_ICE_REG_TURN_SRV_PRFX "ice.turn.server"
+#define NR_ICE_REG_TURN_SRV_ADDR "addr"
+#define NR_ICE_REG_TURN_SRV_PORT "port"
+#define NR_ICE_REG_TURN_SRV_BANDWIDTH "bandwidth"
+#define NR_ICE_REG_TURN_SRV_LIFETIME "lifetime"
+#define NR_ICE_REG_TURN_SRV_USERNAME "username"
+#define NR_ICE_REG_TURN_SRV_PASSWORD "password"
+
+#define NR_ICE_REG_ICE_TCP_DISABLE "ice.tcp.disable"
+#define NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT "ice.tcp.so_sock_count"
+#define NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG "ice.tcp.listen_backlog"
+
+#define NR_ICE_REG_KEEPALIVE_TIMER "ice.keepalive_timer"
+
+#define NR_ICE_REG_TRICKLE_GRACE_PERIOD "ice.trickle_grace_period"
+#define NR_ICE_REG_PREF_FORCE_INTERFACE_NAME "ice.forced_interface_name"
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
new file mode 100644
index 000000000..f9251a280
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
@@ -0,0 +1,380 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_socket.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+#include <assert.h>
+#include <string.h>
+#include "nr_api.h"
+#include "ice_ctx.h"
+#include "stun.h"
+#include "nr_socket_buffered_stun.h"
+#include "nr_socket_multi_tcp.h"
+
+static void nr_ice_socket_readable_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r;
+ nr_ice_stun_ctx *sc1,*sc2;
+ nr_ice_socket *sock=cb_arg;
+ UCHAR buf[9216];
+ char string[256];
+ nr_transport_addr addr;
+ int len;
+ size_t len_s;
+ int is_stun;
+ int is_req;
+ int is_ind;
+ int processed_indication=0;
+
+ nr_socket *stun_srv_sock=sock->sock;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Socket ready to read",sock->ctx->label);
+
+ /* Re-arm first! */
+ if (sock->type != NR_ICE_SOCKET_TYPE_STREAM_TCP) {
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): rearming",sock->ctx->label);
+ NR_ASYNC_WAIT(s,how,nr_ice_socket_readable_cb,cb_arg);
+ }
+
+ if(r=nr_socket_recvfrom(sock->sock,buf,sizeof(buf),&len_s,0,&addr)){
+ if (r != R_WOULDBLOCK && (sock->type != NR_ICE_SOCKET_TYPE_DGRAM)) {
+ /* Report this error upward. Bug 946423 */
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): Error %d on reliable socket(%p). Abandoning.",sock->ctx->label, r, s);
+ }
+ return;
+ }
+
+ /* Deal with the fact that sizeof(int) and sizeof(size_t) may not
+ be the same */
+ if (len_s > (size_t)INT_MAX)
+ return;
+
+ len = (int)len_s;
+
+#ifdef USE_TURN
+ re_process:
+#endif /* USE_TURN */
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Read %d bytes %sfrom %s",sock->ctx->label,len,(processed_indication ? "relayed " : ""),addr.as_string);
+
+ /* First question: is this STUN or not? */
+ is_stun=nr_is_stun_message(buf,len);
+
+ if(is_stun){
+ is_req=nr_is_stun_request_message(buf,len);
+ is_ind=is_req?0:nr_is_stun_indication_message(buf,len);
+
+ snprintf(string, sizeof(string)-1, "ICE(%s): Message is STUN (%s)",sock->ctx->label,
+ is_req ? "request" : (is_ind ? "indication" : "other"));
+ r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)buf, len);
+
+
+ /* We need to offer it to all of our stun contexts
+ to see who bites */
+ sc1=TAILQ_FIRST(&sock->stun_ctxs);
+ while(sc1){
+ sc2=TAILQ_NEXT(sc1,entry);
+
+ r=-1;
+ switch(sc1->type){
+ /* This has been deleted, prune... */
+ case NR_ICE_STUN_NONE:
+ TAILQ_REMOVE(&sock->stun_ctxs,sc1,entry);
+ RFREE(sc1);
+ break;
+
+ case NR_ICE_STUN_CLIENT:
+ if(!(is_req||is_ind)){
+ r=nr_stun_client_process_response(sc1->u.client,buf,len,&addr);
+ }
+ break;
+
+ case NR_ICE_STUN_SERVER:
+ if(is_req){
+ r=nr_stun_server_process_request(sc1->u.server,stun_srv_sock,(char *)buf,len,&addr,NR_STUN_AUTH_RULE_SHORT_TERM);
+ }
+ break;
+#ifdef USE_TURN
+ case NR_ICE_TURN_CLIENT:
+ /* data indications are ok, so don't ignore those */
+ /* Check that this is from the right TURN server address. Else
+ skip */
+ if (nr_transport_addr_cmp(
+ &sc1->u.turn_client.turn_client->turn_server_addr,
+ &addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ break;
+
+ if(!is_req){
+ if(!is_ind)
+ r=nr_turn_client_process_response(sc1->u.turn_client.turn_client,buf,len,&addr);
+ else{
+ nr_transport_addr n_addr;
+ size_t n_len;
+
+ if (processed_indication) {
+ /* Don't allow recursively wrapped indications */
+ r_log(LOG_ICE, LOG_WARNING,
+ "ICE(%s): discarding recursively wrapped indication",
+ sock->ctx->label);
+ break;
+ }
+ /* This is a bit of a hack. If it's a data indication, strip
+ off the TURN framing and re-enter. This works because
+ all STUN processing is on the same physical socket.
+ We don't care about other kinds of indication */
+ r=nr_turn_client_parse_data_indication(
+ sc1->u.turn_client.turn_client, &addr,
+ buf, len, buf, &n_len, len, &n_addr);
+ if(!r){
+ r_log(LOG_ICE,LOG_DEBUG,"Unwrapped a data indication.");
+ len=n_len;
+ nr_transport_addr_copy(&addr,&n_addr);
+ stun_srv_sock=sc1->u.turn_client.turn_sock;
+ processed_indication=1;
+ goto re_process;
+ }
+ }
+ }
+ break;
+#endif /* USE_TURN */
+
+ default:
+ assert(0); /* Can't happen */
+ return;
+ }
+ if(!r) {
+ break;
+ }
+
+ sc1=sc2;
+ }
+ if(!sc1){
+ if (nr_ice_ctx_is_known_id(sock->ctx,((nr_stun_message_header*)buf)->id.octet))
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Message is a retransmit",sock->ctx->label);
+ else
+ r_log(LOG_ICE,LOG_NOTICE,"ICE(%s): Message does not correspond to any registered stun ctx",sock->ctx->label);
+ }
+ }
+ else{
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Message is not STUN",sock->ctx->label);
+
+ nr_ice_ctx_deliver_packet(sock->ctx, sock->component, &addr, buf, len);
+ }
+
+ return;
+ }
+
+int nr_ice_socket_create(nr_ice_ctx *ctx,nr_ice_component *comp, nr_socket *nsock, int type, nr_ice_socket **sockp)
+ {
+ nr_ice_socket *sock=0;
+ NR_SOCKET fd;
+ nr_transport_addr addr;
+ int r,_status;
+
+ if(!(sock=RCALLOC(sizeof(nr_ice_socket))))
+ ABORT(R_NO_MEMORY);
+
+ sock->sock=nsock;
+ sock->ctx=ctx;
+ sock->component=comp;
+
+ if(r=nr_socket_getaddr(nsock, &addr))
+ ABORT(r);
+
+ if (type == NR_ICE_SOCKET_TYPE_DGRAM) {
+ assert(addr.protocol == IPPROTO_UDP);
+ }
+ else {
+ assert(addr.protocol == IPPROTO_TCP);
+ }
+ sock->type=type;
+
+ TAILQ_INIT(&sock->candidates);
+ TAILQ_INIT(&sock->stun_ctxs);
+
+ if (sock->type == NR_ICE_SOCKET_TYPE_DGRAM){
+ if((r=nr_socket_getfd(nsock,&fd)))
+ ABORT(r);
+ NR_ASYNC_WAIT(fd,NR_ASYNC_WAIT_READ,nr_ice_socket_readable_cb,sock);
+ }
+ else if (sock->type == NR_ICE_SOCKET_TYPE_STREAM_TURN) {
+ /* some OS's (e.g. Linux) don't like to see un-connected TCP sockets in
+ * the poll socket set. */
+ nr_socket_buffered_stun_set_readable_cb(nsock,nr_ice_socket_readable_cb,sock);
+ }
+ else if (sock->type == NR_ICE_SOCKET_TYPE_STREAM_TCP) {
+ /* in this case we can't hook up using NR_ASYNC_WAIT, because nr_socket_multi_tcp
+ consists of multiple nr_sockets and file descriptors. */
+ if((r=nr_socket_multi_tcp_set_readable_cb(nsock,nr_ice_socket_readable_cb,sock)))
+ ABORT(r);
+ }
+
+ *sockp=sock;
+
+ _status=0;
+ abort:
+ if(_status) RFREE(sock);
+ return(_status);
+ }
+
+
+int nr_ice_socket_destroy(nr_ice_socket **isockp)
+ {
+ nr_ice_stun_ctx *s1,*s2;
+ nr_ice_socket *isock;
+
+ if(!isockp || !*isockp)
+ return(0);
+
+ isock=*isockp;
+ *isockp=0;
+
+ /* Close the socket */
+ nr_ice_socket_close(isock);
+
+ /* The STUN server */
+ nr_stun_server_ctx_destroy(&isock->stun_server);
+
+ /* Now clean up the STUN ctxs */
+ TAILQ_FOREACH_SAFE(s1, &isock->stun_ctxs, entry, s2){
+ TAILQ_REMOVE(&isock->stun_ctxs, s1, entry);
+ RFREE(s1);
+ }
+
+ RFREE(isock);
+
+ return(0);
+ }
+
+int nr_ice_socket_close(nr_ice_socket *isock)
+ {
+#ifdef NR_SOCKET_IS_VOID_PTR
+ NR_SOCKET fd=NULL;
+ NR_SOCKET no_socket = NULL;
+#else
+ NR_SOCKET fd=-1;
+ NR_SOCKET no_socket = -1;
+#endif
+
+ if (!isock||!isock->sock)
+ return(0);
+
+ if (isock->type != NR_ICE_SOCKET_TYPE_STREAM_TCP){
+ nr_socket_getfd(isock->sock,&fd);
+ assert(isock->sock!=0);
+ if(fd != no_socket){
+ NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ);
+ NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE);
+ }
+ }
+ nr_socket_destroy(&isock->sock);
+
+ return(0);
+ }
+
+int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
+ {
+ nr_ice_stun_ctx *sc=0;
+ int _status;
+
+ if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ sc->type=NR_ICE_STUN_CLIENT;
+ sc->u.client=srv;
+
+ TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry);
+
+ *handle=sc;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_socket_register_stun_server(nr_ice_socket *sock, nr_stun_server_ctx *srv,void **handle)
+ {
+ nr_ice_stun_ctx *sc=0;
+ int _status;
+
+ if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ sc->type=NR_ICE_STUN_SERVER;
+ sc->u.server=srv;
+
+ TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry);
+
+ *handle=sc;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ice_socket_register_turn_client(nr_ice_socket *sock, nr_turn_client_ctx *srv,
+ nr_socket *turn_socket, void **handle)
+ {
+ nr_ice_stun_ctx *sc=0;
+ int _status;
+
+ if(!(sc=RCALLOC(sizeof(nr_ice_stun_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ sc->type=NR_ICE_TURN_CLIENT;
+ sc->u.turn_client.turn_client=srv;
+ sc->u.turn_client.turn_sock=turn_socket;
+
+ TAILQ_INSERT_TAIL(&sock->stun_ctxs,sc,entry);
+
+ *handle=sc;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* Just mark it deregistered. Don't delete it now because it's not safe
+ in the CB, which is where this is likely to be called */
+int nr_ice_socket_deregister(nr_ice_socket *sock, void *handle)
+ {
+ nr_ice_stun_ctx *sc=handle;
+
+ if(!sc)
+ return(0);
+
+ sc->type=NR_ICE_STUN_NONE;
+
+ return(0);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_socket.h b/media/mtransport/third_party/nICEr/src/ice/ice_socket.h
new file mode 100644
index 000000000..b0fba1e1d
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.h
@@ -0,0 +1,97 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_socket_h
+#define _ice_socket_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct nr_ice_stun_ctx_ {
+ int type;
+#define NR_ICE_STUN_NONE 0 /* Deregistered */
+#define NR_ICE_STUN_CLIENT 1
+#define NR_ICE_STUN_SERVER 2
+#define NR_ICE_TURN_CLIENT 3
+
+ union {
+ nr_stun_client_ctx *client;
+ nr_stun_server_ctx *server;
+ struct {
+ nr_turn_client_ctx *turn_client;
+ nr_socket *turn_sock; /* The nr_socket_turn wrapped around
+ turn_client */
+ } turn_client;
+ } u;
+
+ TAILQ_ENTRY(nr_ice_stun_ctx_) entry;
+} nr_ice_stun_ctx;
+
+
+typedef struct nr_ice_socket_ {
+ int type;
+#define NR_ICE_SOCKET_TYPE_DGRAM 1
+#define NR_ICE_SOCKET_TYPE_STREAM_TURN 2
+#define NR_ICE_SOCKET_TYPE_STREAM_TCP 3
+
+ nr_socket *sock;
+ nr_ice_ctx *ctx;
+
+ nr_ice_candidate_head candidates;
+ nr_ice_component *component;
+
+ TAILQ_HEAD(nr_ice_stun_ctx_head_,nr_ice_stun_ctx_) stun_ctxs;
+
+ nr_stun_server_ctx *stun_server;
+ void *stun_server_handle;
+
+ STAILQ_ENTRY(nr_ice_socket_) entry;
+} nr_ice_socket;
+
+typedef STAILQ_HEAD(nr_ice_socket_head_,nr_ice_socket_) nr_ice_socket_head;
+
+int nr_ice_socket_create(struct nr_ice_ctx_ *ctx, struct nr_ice_component_ *comp, nr_socket *nsock, int type, nr_ice_socket **sockp);
+int nr_ice_socket_destroy(nr_ice_socket **isock);
+int nr_ice_socket_close(nr_ice_socket *isock);
+int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle);
+int nr_ice_socket_register_stun_server(nr_ice_socket *sock, nr_stun_server_ctx *srv,void **handle);
+int nr_ice_socket_register_turn_client(nr_ice_socket *sock, nr_turn_client_ctx *srv,nr_socket *turn_socket, void **handle);
+int nr_ice_socket_deregister(nr_ice_socket *sock, void *handle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/net/local_addr.c b/media/mtransport/third_party/nICEr/src/net/local_addr.c
new file mode 100644
index 000000000..c251f2215
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/local_addr.c
@@ -0,0 +1,61 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <nr_api.h>
+#include <string.h>
+#include "local_addr.h"
+
+int nr_local_addr_copy(nr_local_addr *to, nr_local_addr *from)
+ {
+ nr_transport_addr_copy(&(to->addr), &(from->addr));
+ to->interface = from->interface;
+ return(0);
+ }
+
+int nr_local_addr_fmt_info_string(nr_local_addr *addr, char *buf, int len)
+ {
+ int addr_type = addr->interface.type;
+ const char *vpn = (addr_type & NR_INTERFACE_TYPE_VPN) ? "VPN on " : "";
+
+ const char *type = (addr_type & NR_INTERFACE_TYPE_WIRED) ? "wired" :
+ (addr_type & NR_INTERFACE_TYPE_WIFI) ? "wifi" :
+ (addr_type & NR_INTERFACE_TYPE_MOBILE) ? "mobile" :
+ "unknown";
+
+ snprintf(buf, len, "%s%s, estimated speed: %d kbps",
+ vpn, type, addr->interface.estimated_speed);
+ buf[len - 1] = '\0';
+ return (0);
+ }
diff --git a/media/mtransport/third_party/nICEr/src/net/local_addr.h b/media/mtransport/third_party/nICEr/src/net/local_addr.h
new file mode 100644
index 000000000..90e538856
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/local_addr.h
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _local_addr_h
+#define _local_addr_h
+
+#include "transport_addr.h"
+
+typedef struct nr_interface_ {
+ int type;
+#define NR_INTERFACE_TYPE_UNKNOWN 0x0
+#define NR_INTERFACE_TYPE_WIRED 0x1
+#define NR_INTERFACE_TYPE_WIFI 0x2
+#define NR_INTERFACE_TYPE_MOBILE 0x4
+#define NR_INTERFACE_TYPE_VPN 0x8
+ int estimated_speed; /* Speed in kbps */
+} nr_interface;
+
+typedef struct nr_local_addr_ {
+ nr_transport_addr addr;
+ nr_interface interface;
+} nr_local_addr;
+
+int nr_local_addr_copy(nr_local_addr *to, nr_local_addr *from);
+int nr_local_addr_fmt_info_string(nr_local_addr *addr, char *buf, int len);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.c b/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.c
new file mode 100644
index 000000000..75e5f9546
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.c
@@ -0,0 +1,88 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "nr_api.h"
+#include "nr_interface_prioritizer.h"
+#include "transport_addr.h"
+
+int nr_interface_prioritizer_create_int(void *obj,
+ nr_interface_prioritizer_vtbl *vtbl,nr_interface_prioritizer **ifpp)
+ {
+ int _status;
+ nr_interface_prioritizer *ifp=0;
+
+ if(!(ifp=RCALLOC(sizeof(nr_interface_prioritizer))))
+ ABORT(R_NO_MEMORY);
+
+ ifp->obj = obj;
+ ifp->vtbl = vtbl;
+
+ *ifpp = ifp;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_interface_prioritizer_destroy(nr_interface_prioritizer **ifpp)
+ {
+ nr_interface_prioritizer *ifp;
+
+ if (!ifpp || !*ifpp)
+ return(0);
+
+ ifp = *ifpp;
+ *ifpp = 0;
+ ifp->vtbl->destroy(&ifp->obj);
+ RFREE(ifp);
+ return(0);
+ }
+
+int nr_interface_prioritizer_add_interface(nr_interface_prioritizer *ifp,
+ nr_local_addr *addr)
+ {
+ return ifp->vtbl->add_interface(ifp->obj, addr);
+ }
+
+int nr_interface_prioritizer_get_priority(nr_interface_prioritizer *ifp,
+ const char *key, UCHAR *interface_preference)
+ {
+ return ifp->vtbl->get_priority(ifp->obj,key,interface_preference);
+ }
+
+int nr_interface_prioritizer_sort_preference(nr_interface_prioritizer *ifp)
+ {
+ return ifp->vtbl->sort_preference(ifp->obj);
+ }
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.h b/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.h
new file mode 100644
index 000000000..c8a36526c
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_interface_prioritizer.h
@@ -0,0 +1,66 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _nr_interface_prioritizer
+#define _nr_interface_prioritizer
+
+#include "transport_addr.h"
+#include "local_addr.h"
+
+typedef struct nr_interface_prioritizer_vtbl_ {
+ int (*add_interface)(void *obj, nr_local_addr *iface);
+ int (*get_priority)(void *obj, const char *key, UCHAR *pref);
+ int (*sort_preference)(void *obj);
+ int (*destroy)(void **obj);
+} nr_interface_prioritizer_vtbl;
+
+typedef struct nr_interface_prioritizer_ {
+ void *obj;
+ nr_interface_prioritizer_vtbl *vtbl;
+} nr_interface_prioritizer;
+
+int nr_interface_prioritizer_create_int(void *obj, nr_interface_prioritizer_vtbl *vtbl,
+ nr_interface_prioritizer **prioritizer);
+
+int nr_interface_prioritizer_destroy(nr_interface_prioritizer **prioritizer);
+
+int nr_interface_prioritizer_add_interface(nr_interface_prioritizer *prioritizer,
+ nr_local_addr *addr);
+
+int nr_interface_prioritizer_get_priority(nr_interface_prioritizer *prioritizer,
+ const char *key, UCHAR *interface_preference);
+
+int nr_interface_prioritizer_sort_preference(nr_interface_prioritizer *prioritizer);
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
new file mode 100644
index 000000000..b26f2d278
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
@@ -0,0 +1,686 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <nr_api.h>
+
+#include <assert.h>
+
+#include "nr_proxy_tunnel.h"
+
+#define MAX_HTTP_CONNECT_ADDR_SIZE 256
+#define MAX_HTTP_CONNECT_BUFFER_SIZE 1024
+#define MAX_ALPN_LENGTH 64
+#ifndef CRLF
+#define CRLF "\r\n"
+#endif
+#define END_HEADERS CRLF CRLF
+
+typedef enum {
+ PROXY_TUNNEL_NONE=0,
+ PROXY_TUNNEL_REQUESTED,
+ PROXY_TUNNEL_CONNECTED,
+ PROXY_TUNNEL_CLOSED,
+ PROXY_TUNNEL_FAILED
+} nr_socket_proxy_tunnel_state;
+
+typedef struct nr_socket_proxy_tunnel_ {
+ nr_proxy_tunnel_config *config;
+ nr_socket *inner;
+ nr_transport_addr remote_addr;
+ nr_socket_proxy_tunnel_state state;
+ char buffer[MAX_HTTP_CONNECT_BUFFER_SIZE];
+ size_t buffered_bytes;
+ void *resolver_handle;
+} nr_socket_proxy_tunnel;
+
+typedef struct nr_socket_wrapper_factory_proxy_tunnel_ {
+ nr_proxy_tunnel_config *config;
+} nr_socket_wrapper_factory_proxy_tunnel;
+
+static int nr_socket_proxy_tunnel_destroy(void **objpp);
+static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd);
+static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp);
+static int nr_socket_proxy_tunnel_connect(void *sock, nr_transport_addr *addr);
+static int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len, size_t *written);
+static int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen, size_t *len);
+static int nr_socket_proxy_tunnel_close(void *obj);
+
+int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp);
+
+int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
+ nr_socket *inner,
+ nr_socket **socketpp);
+
+int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp);
+
+static nr_socket_vtbl nr_socket_proxy_tunnel_vtbl={
+ 1,
+ nr_socket_proxy_tunnel_destroy,
+ 0,
+ 0,
+ nr_socket_proxy_tunnel_getfd,
+ nr_socket_proxy_tunnel_getaddr,
+ nr_socket_proxy_tunnel_connect,
+ nr_socket_proxy_tunnel_write,
+ nr_socket_proxy_tunnel_read,
+ nr_socket_proxy_tunnel_close
+};
+
+static int send_http_connect(nr_socket_proxy_tunnel *sock)
+{
+ int r, _status;
+ int port;
+ int printed;
+ char addr[MAX_HTTP_CONNECT_ADDR_SIZE];
+ char mesg[MAX_HTTP_CONNECT_ADDR_SIZE + MAX_ALPN_LENGTH + 128];
+ size_t offset = 0;
+ size_t bytes_sent;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect");
+
+ if ((r=nr_transport_addr_get_port(&sock->remote_addr, &port))) {
+ ABORT(r);
+ }
+
+ if ((r=nr_transport_addr_get_addrstring(&sock->remote_addr, addr, sizeof(addr)))) {
+ ABORT(r);
+ }
+
+ printed = snprintf(mesg + offset, sizeof(mesg) - offset,
+ "CONNECT %s:%d HTTP/1.0", addr, port);
+ offset += printed;
+ if (printed < 0 || (offset >= sizeof(mesg))) {
+ ABORT(R_FAILED);
+ }
+
+ if (sock->config->alpn) {
+ printed = snprintf(mesg + offset, sizeof(mesg) - offset,
+ CRLF "ALPN: %s", sock->config->alpn);
+ offset += printed;
+ if (printed < 0 || (offset >= sizeof(mesg))) {
+ ABORT(R_FAILED);
+ }
+ }
+ if (offset + sizeof(END_HEADERS) >= sizeof(mesg)) {
+ ABORT(R_FAILED);
+ }
+ memcpy(mesg + offset, END_HEADERS, strlen(END_HEADERS));
+ offset += strlen(END_HEADERS);
+
+ if ((r=nr_socket_write(sock->inner, mesg, offset, &bytes_sent, 0))) {
+ ABORT(r);
+ }
+
+ if (bytes_sent < offset) {
+ /* TODO(bug 1116583): buffering and wait for */
+ r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
+ ABORT(R_IO_ERROR);
+ }
+
+ sock->state = PROXY_TUNNEL_REQUESTED;
+
+ _status = 0;
+abort:
+ return(_status);
+}
+
+static char *find_http_terminator(char *response, size_t len)
+{
+ char *term = response;
+ char *end = response + len;
+ int N = strlen(END_HEADERS);
+
+ for (; term = memchr(term, '\r', end - term); ++term) {
+ if (end - term >= N && memcmp(term, END_HEADERS, N) == 0) {
+ return term;
+ }
+ }
+
+ return NULL;
+}
+
+static int parse_http_response(char *begin, char *end, unsigned int *status)
+{
+ size_t len = end - begin;
+ char response[MAX_HTTP_CONNECT_BUFFER_SIZE + 1];
+
+ // len should *never* be greater than nr_socket_proxy_tunnel::buffered_bytes.
+ // Which in turn should never be greater nr_socket_proxy_tunnel::buffer size.
+ assert(len <= MAX_HTTP_CONNECT_BUFFER_SIZE);
+ if (len > MAX_HTTP_CONNECT_BUFFER_SIZE) {
+ return R_BAD_DATA;
+ }
+
+ memcpy(response, begin, len);
+ response[len] = '\0';
+
+ // http://www.rfc-editor.org/rfc/rfc7230.txt
+ // status-line = HTTP-version SP status-code SP reason-phrase CRLF
+ // HTTP-version = HTTP-name "/" DIGIT "." DIGIT
+ // HTTP-name = "HTTP" ; "HTTP", case-sensitive
+ // status-code = 3DIGIT
+
+ if (sscanf(response, "HTTP/%*u.%*u %u", status) != 1) {
+ r_log(LOG_GENERIC,LOG_WARNING,"parse_http_response failed to find status (%s)", response);
+ return R_BAD_DATA;
+ }
+
+ return 0;
+}
+
+static int nr_socket_proxy_tunnel_destroy(void **objpp)
+{
+ nr_socket_proxy_tunnel *sock;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_destroy");
+
+ if (!objpp || !*objpp)
+ return 0;
+
+ sock = (nr_socket_proxy_tunnel *)*objpp;
+ *objpp = 0;
+
+ if (sock->resolver_handle) {
+ nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
+ }
+
+ nr_proxy_tunnel_config_destroy(&sock->config);
+ nr_socket_destroy(&sock->inner);
+ RFREE(sock);
+
+ return 0;
+}
+
+static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd)
+{
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getfd");
+
+ return nr_socket_getfd(sock->inner, fd);
+}
+
+static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp)
+{
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getaddr");
+
+ return nr_socket_getaddr(sock->inner, addrp);
+}
+
+static int nr_socket_proxy_tunnel_resolved_cb(void *obj, nr_transport_addr *proxy_addr)
+{
+ int r, _status;
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_resolved_cb");
+
+ /* Mark the socket resolver as completed */
+ sock->resolver_handle = 0;
+
+ if (proxy_addr) {
+ r_log(LOG_GENERIC,LOG_DEBUG,"Resolved proxy address %s -> %s",
+ sock->config->proxy_host, proxy_addr->as_string);
+ }
+ else {
+ r_log(LOG_GENERIC,LOG_WARNING,"Failed to resolve proxy %s",
+ sock->config->proxy_host);
+ /* TODO: Mozilla bug 1241758: because of the callback the return value goes
+ * nowhere, so we can't mark the candidate as failed, so everything depends
+ * on the overall timeouts in this case. */
+ sock->state = PROXY_TUNNEL_FAILED;
+ ABORT(R_NOT_FOUND);
+ }
+
+ if ((r=nr_socket_connect(sock->inner, proxy_addr))) {
+ ABORT(r);
+ }
+
+ _status = 0;
+abort:
+ return(_status);
+}
+
+int nr_socket_proxy_tunnel_connect(void *obj, nr_transport_addr *addr)
+{
+ int r, _status;
+ int has_addr;
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
+ nr_proxy_tunnel_config *config = sock->config;
+ nr_transport_addr proxy_addr, local_addr;
+ nr_resolver_resource resource;
+
+ if ((r=nr_transport_addr_copy(&sock->remote_addr, addr))) {
+ ABORT(r);
+ }
+
+ assert(config->proxy_host);
+
+ /* Check if the proxy_host is already an IP address */
+ has_addr = !nr_str_port_to_transport_addr(config->proxy_host,
+ config->proxy_port, IPPROTO_TCP, &proxy_addr);
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: %s", config->proxy_host);
+
+ if (!has_addr && !config->resolver) {
+ r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect name resolver not configured");
+ ABORT(R_NOT_FOUND);
+ }
+
+ if (!has_addr) {
+ resource.domain_name=config->proxy_host;
+ resource.port=config->proxy_port;
+ resource.stun_turn=NR_RESOLVE_PROTOCOL_TURN;
+ resource.transport_protocol=IPPROTO_TCP;
+
+ if ((r=nr_socket_getaddr(sock->inner, &local_addr))) {
+ r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect failed to get local address");
+ ABORT(r);
+ }
+
+ switch(local_addr.ip_version) {
+ case NR_IPV4:
+ resource.address_family=AF_INET;
+ break;
+ case NR_IPV6:
+ resource.address_family=AF_INET6;
+ break;
+ default:
+ ABORT(R_BAD_ARGS);
+ }
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: nr_resolver_resolve");
+ if ((r=nr_resolver_resolve(config->resolver, &resource,
+ nr_socket_proxy_tunnel_resolved_cb, (void *)sock, &sock->resolver_handle))) {
+ r_log(LOG_GENERIC,LOG_ERR,"Could not invoke DNS resolver");
+ ABORT(r);
+ }
+
+ ABORT(R_WOULDBLOCK);
+ }
+
+ if ((r=nr_socket_connect(sock->inner, &proxy_addr))) {
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len,
+ size_t *written)
+{
+ int r, _status;
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_write");
+
+ if (sock->state >= PROXY_TUNNEL_CLOSED) {
+ return R_FAILED;
+ }
+
+ if (sock->state == PROXY_TUNNEL_NONE) {
+ if ((r=send_http_connect(sock))) {
+ ABORT(r);
+ }
+ }
+
+ if (sock->state != PROXY_TUNNEL_CONNECTED) {
+ return R_WOULDBLOCK;
+ }
+
+ if ((r=nr_socket_write(sock->inner, msg, len, written, 0))) {
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen,
+ size_t *len)
+{
+ int r, _status;
+ char *ptr, *http_term;
+ size_t bytes_read, available_buffer_len, maxlen_int;
+ size_t pending;
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
+ unsigned int http_status;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_read");
+
+ *len = 0;
+
+ if (sock->state >= PROXY_TUNNEL_CLOSED) {
+ return R_FAILED;
+ }
+
+ if (sock->state == PROXY_TUNNEL_CONNECTED) {
+ return nr_socket_read(sock->inner, buf, maxlen, len, 0);
+ }
+
+ if (sock->buffered_bytes >= sizeof(sock->buffer)) {
+ r_log(LOG_GENERIC,LOG_ERR,"buffer filled waiting for CONNECT response");
+ assert(sock->buffered_bytes == sizeof(sock->buffer));
+ ABORT(R_INTERNAL);
+ }
+
+ /* Do not read more than maxlen bytes */
+ available_buffer_len = sizeof(sock->buffer) - sock->buffered_bytes;
+ maxlen_int = maxlen < available_buffer_len ? maxlen : available_buffer_len;
+ if ((r=nr_socket_read(sock->inner, sock->buffer + sock->buffered_bytes,
+ maxlen_int, &bytes_read, 0))) {
+ ABORT(r);
+ }
+
+ sock->buffered_bytes += bytes_read;
+
+ if (http_term = find_http_terminator(sock->buffer, sock->buffered_bytes)) {
+ if ((r = parse_http_response(sock->buffer, http_term, &http_status))) {
+ ABORT(r);
+ }
+
+ /* TODO (bug 1115934): Handle authentication challenges. */
+ if (http_status < 200 || http_status >= 300) {
+ r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
+ http_status);
+ ABORT(R_FAILED);
+ }
+
+ sock->state = PROXY_TUNNEL_CONNECTED;
+
+ ptr = http_term + strlen(END_HEADERS);
+ pending = sock->buffered_bytes - (ptr - sock->buffer);
+
+ if (pending == 0) {
+ ABORT(R_WOULDBLOCK);
+ }
+
+ assert(pending <= maxlen);
+ *len = pending;
+
+ memcpy(buf, ptr, *len);
+ }
+
+ _status=0;
+abort:
+ if (_status && _status != R_WOULDBLOCK) {
+ sock->state = PROXY_TUNNEL_FAILED;
+ }
+ return(_status);
+}
+
+int nr_socket_proxy_tunnel_close(void *obj)
+{
+ nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_close");
+
+ if (sock->resolver_handle) {
+ nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
+ sock->resolver_handle = 0;
+ }
+
+ sock->state = PROXY_TUNNEL_CLOSED;
+
+ return nr_socket_close(sock->inner);
+}
+
+int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **configpp)
+{
+ int _status;
+ nr_proxy_tunnel_config *configp=0;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_create");
+
+ if (!(configp=RCALLOC(sizeof(nr_proxy_tunnel_config))))
+ ABORT(R_NO_MEMORY);
+
+ *configpp=configp;
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **configpp)
+{
+ nr_proxy_tunnel_config *configp;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_destroy");
+
+ if (!configpp || !*configpp)
+ return 0;
+
+ configp = *configpp;
+ *configpp = 0;
+
+ RFREE(configp->proxy_host);
+ RFREE(configp->alpn);
+ RFREE(configp);
+
+ return 0;
+}
+
+int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
+ const char *host, UINT2 port)
+{
+ char *hostdup;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_proxy %s %d", host, port);
+
+ if (!host) {
+ return R_BAD_ARGS;
+ }
+
+ if (!(hostdup = r_strdup(host))) {
+ return R_NO_MEMORY;
+ }
+
+ if (config->proxy_host) {
+ RFREE(config->proxy_host);
+ }
+
+ config->proxy_host = hostdup;
+ config->proxy_port = port;
+
+ return 0;
+}
+
+int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
+ nr_resolver *resolver)
+{
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_resolver");
+
+ config->resolver = resolver;
+
+ return 0;
+}
+
+int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
+ const char *alpn)
+{
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_alpn");
+
+ if (alpn && (strlen(alpn) > MAX_ALPN_LENGTH)) {
+ return R_BAD_ARGS;
+ }
+
+ if (config->alpn) {
+ RFREE(config->alpn);
+ }
+
+ config->alpn = NULL;
+
+ if (alpn) {
+ char *alpndup = r_strdup(alpn);
+
+ if (!alpndup) {
+ return R_NO_MEMORY;
+ }
+
+ config->alpn = alpndup;
+ }
+
+ return 0;
+}
+
+int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp)
+{
+ int r,_status;
+ nr_proxy_tunnel_config *copy = 0;
+
+ if ((r=nr_proxy_tunnel_config_create(&copy)))
+ ABORT(r);
+
+ if ((r=nr_proxy_tunnel_config_set_proxy(copy, config->proxy_host, config->proxy_port)))
+ ABORT(r);
+
+ if ((r=nr_proxy_tunnel_config_set_resolver(copy, config->resolver)))
+ ABORT(r);
+
+ if ((r=nr_proxy_tunnel_config_set_alpn(copy, config->alpn)))
+ ABORT(r);
+
+ *copypp = copy;
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_proxy_tunnel_config_destroy(&copy);
+ }
+ return(_status);
+}
+
+
+int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
+ nr_socket *inner,
+ nr_socket **socketpp)
+{
+ int r, _status;
+ nr_socket_proxy_tunnel *sock=0;
+ void *sockv;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_create");
+
+ if (!config) {
+ ABORT(R_BAD_ARGS);
+ }
+
+ if (!(sock=RCALLOC(sizeof(nr_socket_proxy_tunnel)))) {
+ ABORT(R_NO_MEMORY);
+ }
+
+ sock->inner = inner;
+
+ if ((r=nr_proxy_tunnel_config_copy(config, &sock->config)))
+ ABORT(r);
+
+ if ((r=nr_socket_create_int(sock, &nr_socket_proxy_tunnel_vtbl, socketpp))) {
+ ABORT(r);
+ }
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_created");
+
+ _status=0;
+abort:
+ if (_status) {
+ sockv = sock;
+ nr_socket_proxy_tunnel_destroy(&sockv);
+ }
+ return(_status);
+}
+
+int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
+ nr_socket *inner,
+ nr_socket **socketpp)
+{
+ nr_socket_wrapper_factory_proxy_tunnel *wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)obj;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_wrap");
+
+ return nr_socket_proxy_tunnel_create(wrapper->config, inner, socketpp);
+}
+
+
+int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp) {
+ nr_socket_wrapper_factory_proxy_tunnel *wrapper;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_destroy");
+
+ if (!objpp || !*objpp)
+ return 0;
+
+ wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)*objpp;
+ *objpp = 0;
+
+ nr_proxy_tunnel_config_destroy(&wrapper->config);
+ RFREE(wrapper);
+
+ return 0;
+}
+
+static nr_socket_wrapper_factory_vtbl proxy_tunnel_wrapper_vtbl = {
+ nr_socket_wrapper_factory_proxy_tunnel_wrap,
+ nr_socket_wrapper_factory_proxy_tunnel_destroy
+};
+
+int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
+ nr_socket_wrapper_factory **factory) {
+ int r,_status;
+ nr_socket_wrapper_factory_proxy_tunnel *wrapper=0;
+ void *wrapperv;
+
+ r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_create");
+
+ if (!(wrapper=RCALLOC(sizeof(nr_socket_wrapper_factory_proxy_tunnel))))
+ ABORT(R_NO_MEMORY);
+
+ if ((r=nr_proxy_tunnel_config_copy(config, &wrapper->config)))
+ ABORT(r);
+
+ if ((r=nr_socket_wrapper_factory_create_int(wrapper, &proxy_tunnel_wrapper_vtbl, factory)))
+ ABORT(r);
+
+ _status=0;
+abort:
+ if (_status) {
+ wrapperv = wrapper;
+ nr_socket_wrapper_factory_proxy_tunnel_destroy(&wrapperv);
+ }
+ return(_status);
+}
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
new file mode 100644
index 000000000..e9c4393e1
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _nr_proxy_tunnel_h
+#define _nr_proxy_tunnel_h
+
+#include "nr_socket.h"
+#include "nr_resolver.h"
+#include "nr_socket_wrapper.h"
+
+typedef struct nr_proxy_tunnel_config_ {
+ nr_resolver *resolver;
+ char *proxy_host;
+ UINT2 proxy_port;
+ char *alpn;
+} nr_proxy_tunnel_config;
+
+int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **config);
+
+int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **config);
+
+int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
+ const char* host, UINT2 port);
+
+int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
+ nr_resolver *resolver);
+
+int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
+ const char *alpn);
+
+int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
+ nr_socket *inner,
+ nr_socket **socketpp);
+
+int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
+ nr_socket_wrapper_factory **factory);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_resolver.c b/media/mtransport/third_party/nICEr/src/net/nr_resolver.c
new file mode 100644
index 000000000..4dbf1bbe9
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_resolver.c
@@ -0,0 +1,85 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <nr_api.h>
+#include "nr_resolver.h"
+
+int nr_resolver_create_int(void *obj, nr_resolver_vtbl *vtbl, nr_resolver **resolverp)
+{
+ int _status;
+ nr_resolver *resolver=0;
+
+ if (!(resolver=RCALLOC(sizeof(nr_resolver))))
+ ABORT(R_NO_MEMORY);
+
+ resolver->obj=obj;
+ resolver->vtbl=vtbl;
+
+ *resolverp=resolver;
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_resolver_destroy(nr_resolver **resolverp)
+{
+ nr_resolver *resolver;
+
+ if(!resolverp || !*resolverp)
+ return(0);
+
+ resolver=*resolverp;
+ *resolverp=0;
+
+ resolver->vtbl->destroy(&resolver->obj);
+
+ RFREE(resolver);
+
+ return(0);
+}
+
+int nr_resolver_resolve(nr_resolver *resolver,
+ nr_resolver_resource *resource,
+ int (*cb)(void *cb_arg, nr_transport_addr *addr),
+ void *cb_arg,
+ void **handle)
+{
+ return resolver->vtbl->resolve(resolver->obj, resource, cb, cb_arg, handle);
+}
+
+int nr_resolver_cancel(nr_resolver *resolver, void *handle)
+{
+ return resolver->vtbl->cancel(resolver->obj, handle);
+}
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_resolver.h b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h
new file mode 100644
index 000000000..376ba9998
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_resolver.h
@@ -0,0 +1,96 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _nr_resolver_h
+#define _nr_resolver_h
+
+#include "transport_addr.h"
+
+#define NR_RESOLVE_PROTOCOL_STUN 1
+#define NR_RESOLVE_PROTOCOL_TURN 2
+
+typedef struct nr_resolver_resource_ {
+ const char *domain_name;
+ UINT2 port;
+ int stun_turn;
+ UCHAR transport_protocol;
+ UCHAR address_family;
+} nr_resolver_resource;
+
+typedef struct nr_resolver_vtbl_ {
+ int (*destroy)(void **obj);
+ int (*resolve)(void *obj,
+ nr_resolver_resource *resource,
+ int (*cb)(void *cb_arg, nr_transport_addr *addr),
+ void *cb_arg,
+ void **handle);
+ int (*cancel)(void *obj, void *handle);
+} nr_resolver_vtbl;
+
+typedef struct nr_resolver_ {
+ void *obj;
+ nr_resolver_vtbl *vtbl;
+} nr_resolver;
+
+
+/*
+ The convention here is that the provider of this interface
+ must generate a void *obj, and a vtbl and then call
+ nr_resolver_create_int() to allocate the generic wrapper
+ object.
+
+ The vtbl must contain implementations for all the functions
+ listed.
+
+ The nr_resolver_destroy() function (and hence vtbl->destroy)
+ will be called when the consumer of the resolver is done
+ with it. That is the signal that it is safe to clean up
+ the resources associated with obj. No other function will
+ be called afterwards.
+*/
+int nr_resolver_create_int(void *obj, nr_resolver_vtbl *vtbl,
+ nr_resolver **resolverp);
+int nr_resolver_destroy(nr_resolver **resolverp);
+
+/* Request resolution of a domain */
+int nr_resolver_resolve(nr_resolver *resolver,
+ nr_resolver_resource *resource,
+ int (*cb)(void *cb_arg, nr_transport_addr *addr),
+ void *cb_arg,
+ void **handle);
+
+/* Cancel a requested resolution. No callback will fire. */
+int nr_resolver_cancel(nr_resolver *resolver, void *handle);
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket.c b/media/mtransport/third_party/nICEr/src/net/nr_socket.c
new file mode 100644
index 000000000..d12f26454
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket.c
@@ -0,0 +1,191 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: nr_socket.c,v 1.2 2008/04/28 17:59:02 ekr Exp $";
+
+#include <assert.h>
+#include <nr_api.h>
+#include "nr_socket.h"
+#include "local_addr.h"
+
+#define CHECK_DEFINED(f) assert(sock->vtbl->f); if (!sock->vtbl->f) ERETURN(R_INTERNAL);
+int nr_socket_create_int(void *obj, nr_socket_vtbl *vtbl, nr_socket **sockp)
+ {
+ int _status;
+ nr_socket *sock=0;
+
+ if(!(sock=RCALLOC(sizeof(nr_socket))))
+ ABORT(R_NO_MEMORY);
+
+ assert(vtbl->version >= 1 && vtbl->version <= 2);
+ if (vtbl->version < 1 || vtbl->version > 2)
+ ABORT(R_INTERNAL);
+
+ sock->obj=obj;
+ sock->vtbl=vtbl;
+
+ *sockp=sock;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_socket_destroy(nr_socket **sockp)
+ {
+ nr_socket *sock;
+
+ if(!sockp || !*sockp)
+ return(0);
+
+
+ sock=*sockp;
+ *sockp=0;
+
+ CHECK_DEFINED(destroy);
+
+ assert(sock->vtbl);
+ if (sock->vtbl)
+ sock->vtbl->destroy(&sock->obj);
+
+ RFREE(sock);
+
+ return(0);
+ }
+
+int nr_socket_sendto(nr_socket *sock,const void *msg, size_t len, int flags,
+ nr_transport_addr *addr)
+ {
+ CHECK_DEFINED(ssendto);
+ return sock->vtbl->ssendto(sock->obj,msg,len,flags,addr);
+ }
+
+int nr_socket_recvfrom(nr_socket *sock,void * restrict buf, size_t maxlen,
+ size_t *len, int flags, nr_transport_addr *addr)
+ {
+ CHECK_DEFINED(srecvfrom);
+ return sock->vtbl->srecvfrom(sock->obj, buf, maxlen, len, flags, addr);
+ }
+
+int nr_socket_getfd(nr_socket *sock, NR_SOCKET *fd)
+ {
+ CHECK_DEFINED(getfd);
+ return sock->vtbl->getfd(sock->obj, fd);
+ }
+
+int nr_socket_getaddr(nr_socket *sock, nr_transport_addr *addrp)
+ {
+ CHECK_DEFINED(getaddr);
+ return sock->vtbl->getaddr(sock->obj, addrp);
+ }
+
+int nr_socket_close(nr_socket *sock)
+ {
+ CHECK_DEFINED(close);
+ return sock->vtbl->close(sock->obj);
+ }
+
+int nr_socket_connect(nr_socket *sock, nr_transport_addr *addr)
+ {
+ CHECK_DEFINED(connect);
+ return sock->vtbl->connect(sock->obj, addr);
+ }
+
+int nr_socket_write(nr_socket *sock,const void *msg, size_t len, size_t *written, int flags)
+ {
+ CHECK_DEFINED(swrite);
+ return sock->vtbl->swrite(sock->obj, msg, len, written);
+ }
+
+
+int nr_socket_read(nr_socket *sock,void * restrict buf, size_t maxlen,
+ size_t *len, int flags)
+ {
+ CHECK_DEFINED(sread);
+ return sock->vtbl->sread(sock->obj, buf, maxlen, len);
+ }
+
+int nr_socket_listen(nr_socket *sock, int backlog)
+ {
+ assert(sock->vtbl->version >=2 );
+ CHECK_DEFINED(listen);
+ return sock->vtbl->listen(sock->obj, backlog);
+ }
+
+int nr_socket_accept(nr_socket *sock, nr_transport_addr *addrp, nr_socket **sockp)
+{
+ assert(sock->vtbl->version >= 2);
+ CHECK_DEFINED(accept);
+ return sock->vtbl->accept(sock->obj, addrp, sockp);
+}
+
+
+int nr_socket_factory_create_int(void *obj,
+ nr_socket_factory_vtbl *vtbl, nr_socket_factory **factorypp)
+ {
+ int _status;
+ nr_socket_factory *factoryp=0;
+
+ if(!(factoryp=RCALLOC(sizeof(nr_socket_factory))))
+ ABORT(R_NO_MEMORY);
+
+ factoryp->obj = obj;
+ factoryp->vtbl = vtbl;
+
+ *factorypp = factoryp;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_socket_factory_destroy(nr_socket_factory **factorypp)
+ {
+ nr_socket_factory *factoryp;
+
+ if (!factorypp || !*factorypp)
+ return (0);
+
+ factoryp = *factorypp;
+ *factorypp = NULL;
+ factoryp->vtbl->destroy(&factoryp->obj);
+ RFREE(factoryp);
+ return (0);
+ }
+
+int nr_socket_factory_create_socket(nr_socket_factory *factory, nr_transport_addr *addr, nr_socket **sockp)
+ {
+ return factory->vtbl->create_socket(factory->obj, addr, sockp);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket.h b/media/mtransport/third_party/nICEr/src/net/nr_socket.h
new file mode 100644
index 000000000..95f62e413
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket.h
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _nr_socket_h
+#define _nr_socket_h
+
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#endif
+
+#include "transport_addr.h"
+#include "csi_platform.h"
+
+#ifdef __cplusplus
+#define restrict
+#elif defined(WIN32)
+#define restrict __restrict
+#endif
+
+typedef enum {
+ TCP_TYPE_NONE=0,
+ TCP_TYPE_ACTIVE,
+ TCP_TYPE_PASSIVE,
+ TCP_TYPE_SO,
+ TCP_TYPE_MAX
+} nr_socket_tcp_type;
+
+typedef struct nr_socket_ nr_socket;
+
+typedef struct nr_socket_vtbl_ {
+ UINT4 version; /* Currently 2 */
+ int (*destroy)(void **obj);
+ int (*ssendto)(void *obj,const void *msg, size_t len, int flags,
+ nr_transport_addr *addr);
+ int (*srecvfrom)(void *obj,void * restrict buf, size_t maxlen, size_t *len, int flags,
+ nr_transport_addr *addr);
+ int (*getfd)(void *obj, NR_SOCKET *fd);
+ int (*getaddr)(void *obj, nr_transport_addr *addrp);
+ int (*connect)(void *obj, nr_transport_addr *addr);
+ int (*swrite)(void *obj,const void *msg, size_t len, size_t *written);
+ int (*sread)(void *obj,void * restrict buf, size_t maxlen, size_t *len);
+ int (*close)(void *obj);
+
+ /* available since version 2 */
+ int (*listen)(void *obj, int backlog);
+ int (*accept)(void *obj, nr_transport_addr *addrp, nr_socket **sockp);
+} nr_socket_vtbl;
+
+
+struct nr_socket_ {
+ void *obj;
+ nr_socket_vtbl *vtbl;
+};
+
+typedef struct nr_socket_factory_vtbl_ {
+ int (*create_socket)(void *obj, nr_transport_addr *addr, nr_socket **sockp);
+ int (*destroy)(void **obj);
+} nr_socket_factory_vtbl;
+
+typedef struct nr_socket_factory_ {
+ void *obj;
+ nr_socket_factory_vtbl *vtbl;
+} nr_socket_factory;
+
+/* To be called by constructors */
+int nr_socket_create_int(void *obj, nr_socket_vtbl *vtbl, nr_socket **sockp);
+int nr_socket_destroy(nr_socket **sockp);
+int nr_socket_sendto(nr_socket *sock,const void *msg, size_t len,
+ int flags,nr_transport_addr *addr);
+int nr_socket_recvfrom(nr_socket *sock,void * restrict buf, size_t maxlen,
+ size_t *len, int flags, nr_transport_addr *addr);
+int nr_socket_getfd(nr_socket *sock, NR_SOCKET *fd);
+int nr_socket_getaddr(nr_socket *sock, nr_transport_addr *addrp);
+int nr_socket_close(nr_socket *sock);
+int nr_socket_connect(nr_socket *sock, nr_transport_addr *addr);
+int nr_socket_write(nr_socket *sock,const void *msg, size_t len, size_t *written, int flags);
+int nr_socket_read(nr_socket *sock, void * restrict buf, size_t maxlen, size_t *len, int flags);
+int nr_socket_listen(nr_socket *sock, int backlog);
+int nr_socket_accept(nr_socket *sock, nr_transport_addr *addrp, nr_socket **sockp);
+
+int nr_socket_factory_create_int(void *obj, nr_socket_factory_vtbl *vtbl, nr_socket_factory **factorypp);
+int nr_socket_factory_destroy(nr_socket_factory **factoryp);
+int nr_socket_factory_create_socket(nr_socket_factory *factory, nr_transport_addr *addr, nr_socket **sockp);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket_local.h b/media/mtransport/third_party/nICEr/src/net/nr_socket_local.h
new file mode 100644
index 000000000..a2f813ff6
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket_local.h
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _nr_socket_local_h
+#define _nr_socket_local_h
+
+int nr_socket_local_create(void *obj, nr_transport_addr *addr, nr_socket **sockp);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c b/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c
new file mode 100644
index 000000000..12bbea795
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.c
@@ -0,0 +1,620 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2014, Mozilla
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <assert.h>
+#include <sys/types.h>
+
+#include "nr_api.h"
+#include "ice_ctx.h"
+#include "nr_socket.h"
+#include "nr_socket_local.h"
+#include "nr_socket_multi_tcp.h"
+#include "nr_socket_buffered_stun.h"
+#include "async_timer.h"
+
+typedef struct nr_tcp_socket_ctx_ {
+ nr_socket * inner;
+ nr_transport_addr remote_addr;
+ int is_framed;
+
+ TAILQ_ENTRY(nr_tcp_socket_ctx_) entry;
+} nr_tcp_socket_ctx;
+
+typedef TAILQ_HEAD(nr_tcp_socket_head_,nr_tcp_socket_ctx_) nr_tcp_socket_head;
+
+static void nr_tcp_socket_readable_cb(NR_SOCKET s, int how, void *arg);
+
+static int nr_tcp_socket_ctx_destroy(nr_tcp_socket_ctx **objp)
+ {
+ nr_tcp_socket_ctx *sock;
+
+ if (!objp || !*objp)
+ return(0);
+
+ sock=*objp;
+ *objp=0;
+
+ nr_socket_destroy(&sock->inner);
+
+ RFREE(sock);
+
+ return(0);
+ }
+
+/* This takes ownership of nrsock whether it fails or not. */
+static int nr_tcp_socket_ctx_create(nr_socket *nrsock, int is_framed,
+ int max_pending, nr_tcp_socket_ctx **sockp)
+ {
+ int r, _status;
+ nr_tcp_socket_ctx *sock = 0;
+ nr_socket *tcpsock;
+
+ if (!(sock = RCALLOC(sizeof(nr_tcp_socket_ctx)))) {
+ nr_socket_destroy(&nrsock);
+ ABORT(R_NO_MEMORY);
+ }
+
+ if ((r=nr_socket_buffered_stun_create(nrsock, max_pending, is_framed ? ICE_TCP_FRAMING : TURN_TCP_FRAMING, &tcpsock))){
+ nr_socket_destroy(&nrsock);
+ ABORT(r);
+ }
+
+ sock->inner=tcpsock;
+ sock->is_framed=is_framed;
+
+ if ((r=nr_ip4_port_to_transport_addr(ntohl(INADDR_ANY), 0, IPPROTO_TCP, &sock->remote_addr)))
+ ABORT(r);
+
+ *sockp=sock;
+
+ _status=0;
+abort:
+ if (_status) {
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s failed with error %d",__FILE__,__LINE__,__FUNCTION__,_status);
+ nr_tcp_socket_ctx_destroy(&sock);
+ }
+ return(_status);
+ }
+
+static int nr_tcp_socket_ctx_initialize(nr_tcp_socket_ctx *tcpsock,
+ nr_transport_addr *addr, void* cb_arg)
+ {
+ int r, _status;
+ NR_SOCKET fd;
+
+ if ((r=nr_transport_addr_copy(&tcpsock->remote_addr, addr)))
+ ABORT(r);
+ if ((r=nr_socket_getfd(tcpsock->inner, &fd)))
+ ABORT(r);
+ NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, nr_tcp_socket_readable_cb, cb_arg);
+
+ _status=0;
+ abort:
+ if (_status)
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,_status);
+ return(_status);
+ }
+
+typedef struct nr_socket_multi_tcp_ {
+ nr_ice_ctx *ctx;
+ nr_socket *listen_socket;
+ nr_tcp_socket_head sockets;
+ nr_socket_tcp_type tcp_type;
+ nr_transport_addr addr;
+ NR_async_cb readable_cb;
+ void *readable_cb_arg;
+ int max_pending;
+} nr_socket_multi_tcp;
+
+static int nr_socket_multi_tcp_destroy(void **objp);
+static int nr_socket_multi_tcp_sendto(void *obj,const void *msg, size_t len,
+ int flags, nr_transport_addr *to);
+static int nr_socket_multi_tcp_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *from);
+static int nr_socket_multi_tcp_getaddr(void *obj, nr_transport_addr *addrp);
+static int nr_socket_multi_tcp_close(void *obj);
+static int nr_socket_multi_tcp_connect(void *sock, nr_transport_addr *addr);
+static int nr_socket_multi_tcp_listen(void *obj, int backlog);
+
+static nr_socket_vtbl nr_socket_multi_tcp_vtbl={
+ 2,
+ nr_socket_multi_tcp_destroy,
+ nr_socket_multi_tcp_sendto,
+ nr_socket_multi_tcp_recvfrom,
+ 0,
+ nr_socket_multi_tcp_getaddr,
+ nr_socket_multi_tcp_connect,
+ 0,
+ 0,
+ nr_socket_multi_tcp_close,
+ nr_socket_multi_tcp_listen,
+ 0
+};
+
+static int nr_socket_multi_tcp_create_stun_server_socket(
+ nr_socket_multi_tcp *sock, nr_ice_stun_server * stun_server,
+ nr_transport_addr *addr, int max_pending)
+ {
+ int r, _status;
+ nr_tcp_socket_ctx *tcp_socket_ctx=0;
+ nr_socket * nrsock;
+
+ if (stun_server->transport!=IPPROTO_TCP) {
+ r_log(LOG_ICE,LOG_INFO,"%s:%d function %s skipping UDP STUN server(addr:%s)",__FILE__,__LINE__,__FUNCTION__,stun_server->u.addr.as_string);
+ ABORT(R_BAD_ARGS);
+ }
+
+ if (stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR &&
+ nr_transport_addr_cmp(&stun_server->u.addr,addr,NR_TRANSPORT_ADDR_CMP_MODE_VERSION)) {
+ r_log(LOG_ICE,LOG_INFO,"%s:%d function %s skipping STUN with different IP version (%u) than local socket (%u),",__FILE__,__LINE__,__FUNCTION__,stun_server->u.addr.ip_version,addr->ip_version);
+ ABORT(R_BAD_ARGS);
+ }
+
+ if ((r=nr_socket_factory_create_socket(sock->ctx->socket_factory,addr, &nrsock)))
+ ABORT(r);
+
+ /* This takes ownership of nrsock whether it fails or not. */
+ if ((r=nr_tcp_socket_ctx_create(nrsock, 0, max_pending, &tcp_socket_ctx)))
+ ABORT(r);
+
+ if (stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR) {
+ nr_transport_addr stun_server_addr;
+
+ nr_transport_addr_copy(&stun_server_addr, &stun_server->u.addr);
+ r=nr_socket_connect(tcp_socket_ctx->inner, &stun_server_addr);
+ if (r && r!=R_WOULDBLOCK) {
+ r_log(LOG_ICE,LOG_WARNING,"%s:%d function %s connect to STUN server(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,stun_server_addr.as_string,r);
+ ABORT(r);
+ }
+
+ if ((r=nr_tcp_socket_ctx_initialize(tcp_socket_ctx, &stun_server_addr, sock)))
+ ABORT(r);
+ }
+
+ TAILQ_INSERT_TAIL(&sock->sockets, tcp_socket_ctx, entry);
+
+ _status=0;
+ abort:
+ if (_status) {
+ nr_tcp_socket_ctx_destroy(&tcp_socket_ctx);
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,_status);
+ }
+ return(_status);
+ }
+
+int nr_socket_multi_tcp_create(struct nr_ice_ctx_ *ctx,
+ nr_transport_addr *addr, nr_socket_tcp_type tcp_type,
+ int precreated_so_count, int max_pending, nr_socket **sockp)
+ {
+ int i=0;
+ int r, _status;
+ nr_socket_multi_tcp *sock=0;
+ nr_tcp_socket_ctx *tcp_socket_ctx;
+ nr_socket * nrsock;
+
+ if (!(sock = RCALLOC(sizeof(nr_socket_multi_tcp))))
+ ABORT(R_NO_MEMORY);
+
+ TAILQ_INIT(&sock->sockets);
+
+ sock->ctx=ctx;
+ sock->max_pending=max_pending;
+ sock->tcp_type=tcp_type;
+ nr_transport_addr_copy(&sock->addr, addr);
+
+ if((tcp_type==TCP_TYPE_PASSIVE) &&
+ ((r=nr_socket_factory_create_socket(sock->ctx->socket_factory, addr, &sock->listen_socket))))
+ ABORT(r);
+
+ if (tcp_type!=TCP_TYPE_ACTIVE) {
+ if (sock->ctx && sock->ctx->stun_servers) {
+ for (i=0; i<sock->ctx->stun_server_ct; ++i) {
+ if ((r=nr_socket_multi_tcp_create_stun_server_socket(sock,
+ sock->ctx->stun_servers+i, addr, max_pending))) {
+ if (r!=R_BAD_ARGS) {
+ r_log(LOG_ICE,LOG_WARNING,"%s:%d function %s failed to connect STUN server from addr:%s with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,r);
+ }
+ }
+ }
+ }
+ if (sock->ctx && sock->ctx->turn_servers) {
+ for (i=0; i<sock->ctx->turn_server_ct; ++i) {
+ if ((r=nr_socket_multi_tcp_create_stun_server_socket(sock,
+ &(sock->ctx->turn_servers[i]).turn_server, addr, max_pending))) {
+ if (r!=R_BAD_ARGS) {
+ r_log(LOG_ICE,LOG_WARNING,"%s:%d function %s failed to connect TURN server from addr:%s with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,r);
+ }
+ }
+ }
+ }
+ }
+
+ if ((tcp_type==TCP_TYPE_SO)) {
+ for (i=0; i<precreated_so_count; ++i) {
+
+ if ((r=nr_socket_factory_create_socket(sock->ctx->socket_factory, addr, &nrsock)))
+ ABORT(r);
+
+ /* This takes ownership of nrsock whether it fails or not. */
+ if ((r=nr_tcp_socket_ctx_create(nrsock, 1, max_pending, &tcp_socket_ctx))){
+ ABORT(r);
+ }
+ TAILQ_INSERT_TAIL(&sock->sockets, tcp_socket_ctx, entry);
+ }
+ }
+
+ if((r=nr_socket_create_int(sock, &nr_socket_multi_tcp_vtbl, sockp)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (_status) {
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,_status);
+ nr_socket_multi_tcp_destroy((void**)&sock);
+ }
+ return(_status);
+ }
+
+int nr_socket_multi_tcp_set_readable_cb(nr_socket *sock,
+ NR_async_cb readable_cb, void *readable_cb_arg)
+ {
+ nr_socket_multi_tcp *mtcp_sock = (nr_socket_multi_tcp *)sock->obj;
+
+ mtcp_sock->readable_cb=readable_cb;
+ mtcp_sock->readable_cb_arg=readable_cb_arg;
+
+ return 0;
+ }
+
+#define PREALLOC_CONNECT_FRAMED 0
+#define PREALLOC_CONNECT_NON_FRAMED 1
+#define PREALLOC_DONT_CONNECT_UNLESS_SO 2
+
+static int nr_socket_multi_tcp_get_sock_connected_to(nr_socket_multi_tcp *sock,
+ nr_transport_addr *to, int preallocated_connect_mode, nr_socket **ret_sock)
+ {
+ int r, _status;
+ nr_tcp_socket_ctx *tcp_sock_ctx;
+ nr_socket * nrsock;
+
+ to->protocol=IPPROTO_TCP;
+
+ TAILQ_FOREACH(tcp_sock_ctx, &sock->sockets, entry) {
+ if (!nr_transport_addr_is_wildcard(&tcp_sock_ctx->remote_addr)) {
+ if (!nr_transport_addr_cmp(to, &tcp_sock_ctx->remote_addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ *ret_sock=tcp_sock_ctx->inner;
+ return(0);
+ }
+ }
+ }
+
+ tcp_sock_ctx=NULL;
+ /* not connected yet */
+ if (sock->tcp_type != TCP_TYPE_ACTIVE) {
+ if (preallocated_connect_mode == PREALLOC_DONT_CONNECT_UNLESS_SO && sock->tcp_type != TCP_TYPE_SO)
+ ABORT(R_FAILED);
+
+ /* find free preallocated socket and connect */
+ TAILQ_FOREACH(tcp_sock_ctx, &sock->sockets, entry) {
+ if (nr_transport_addr_is_wildcard(&tcp_sock_ctx->remote_addr)) {
+ if (preallocated_connect_mode == PREALLOC_CONNECT_NON_FRAMED && tcp_sock_ctx->is_framed)
+ continue;
+ if (preallocated_connect_mode != PREALLOC_CONNECT_NON_FRAMED && !tcp_sock_ctx->is_framed)
+ continue;
+
+ if ((r=nr_socket_connect(tcp_sock_ctx->inner, to))){
+ if (r!=R_WOULDBLOCK)
+ ABORT(r);
+ }
+
+ if ((r=nr_tcp_socket_ctx_initialize(tcp_sock_ctx, to, sock)))
+ ABORT(r);
+
+ *ret_sock=tcp_sock_ctx->inner;
+
+ return(0);
+ }
+ }
+ tcp_sock_ctx=NULL;
+ ABORT(R_FAILED);
+ }
+
+ /* if active type - create new socket for each new remote addr */
+ assert(sock->tcp_type == TCP_TYPE_ACTIVE);
+
+ if ((r=nr_socket_factory_create_socket(sock->ctx->socket_factory, &sock->addr, &nrsock)))
+ ABORT(r);
+
+ /* This takes ownership of nrsock whether it fails or not. */
+ if ((r=nr_tcp_socket_ctx_create(nrsock, 1, sock->max_pending, &tcp_sock_ctx))){
+ ABORT(r);
+ }
+
+ TAILQ_INSERT_TAIL(&sock->sockets, tcp_sock_ctx, entry);
+
+ if ((r=nr_socket_connect(tcp_sock_ctx->inner, to))){
+ if (r!=R_WOULDBLOCK)
+ ABORT(r);
+ }
+
+ if ((r=nr_tcp_socket_ctx_initialize(tcp_sock_ctx, to, sock)))
+ ABORT(r);
+
+ *ret_sock=tcp_sock_ctx->inner;
+ tcp_sock_ctx=NULL;
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (tcp_sock_ctx) {
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s failed with error %d, tcp_sock_ctx remote_addr: %s",__FILE__,__LINE__,__FUNCTION__,_status, tcp_sock_ctx->remote_addr.as_string);
+ TAILQ_REMOVE(&sock->sockets, tcp_sock_ctx, entry);
+ nr_tcp_socket_ctx_destroy(&tcp_sock_ctx);
+ } else {
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s failed with error %d, tcp_sock_ctx=NULL",__FILE__,__LINE__,__FUNCTION__,_status);
+ }
+ }
+
+ return(_status);
+ }
+
+int nr_socket_multi_tcp_stun_server_connect(nr_socket *sock,
+ nr_transport_addr *addr)
+ {
+ int r, _status;
+ nr_socket_multi_tcp *mtcp_sock = (nr_socket_multi_tcp *)sock->obj;
+ nr_socket *nrsock;
+
+ assert(mtcp_sock->tcp_type != TCP_TYPE_ACTIVE);
+ if (mtcp_sock->tcp_type == TCP_TYPE_ACTIVE)
+ ABORT(R_INTERNAL);
+
+ if ((r=nr_socket_multi_tcp_get_sock_connected_to(mtcp_sock,addr,PREALLOC_CONNECT_NON_FRAMED,&nrsock)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (_status)
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,_status);
+ return(_status);
+ }
+
+static int nr_socket_multi_tcp_destroy(void **objp)
+ {
+ nr_socket_multi_tcp *sock;
+ nr_tcp_socket_ctx *tcpsock;
+ NR_SOCKET fd;
+
+ if (!objp || !*objp)
+ return 0;
+
+ sock=(nr_socket_multi_tcp *)*objp;
+ *objp=0;
+
+ /* Cancel waiting on the socket */
+ if (sock->listen_socket && !nr_socket_getfd(sock->listen_socket, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
+ }
+
+ nr_socket_destroy(&sock->listen_socket);
+
+ while (!TAILQ_EMPTY(&sock->sockets)) {
+
+ tcpsock = TAILQ_FIRST(&sock->sockets);
+ TAILQ_REMOVE(&sock->sockets, tcpsock, entry);
+
+ if (!nr_socket_getfd(tcpsock->inner, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
+ }
+
+ nr_tcp_socket_ctx_destroy(&tcpsock);
+ }
+
+ RFREE(sock);
+
+ return 0;
+ }
+
+static int nr_socket_multi_tcp_sendto(void *obj, const void *msg, size_t len,
+ int flags, nr_transport_addr *to)
+ {
+ int r, _status;
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+ nr_socket *nrsock;
+
+ if ((r=nr_socket_multi_tcp_get_sock_connected_to(sock, to,
+ PREALLOC_DONT_CONNECT_UNLESS_SO, &nrsock)))
+ ABORT(r);
+
+ if((r=nr_socket_sendto(nrsock, msg, len, flags, to)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (_status)
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(to:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,to->as_string,_status);
+
+ return(_status);
+}
+
+static int nr_socket_multi_tcp_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *from)
+ {
+ int r, _status = 0;
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+ nr_tcp_socket_ctx *tcpsock;
+
+ if (TAILQ_EMPTY(&sock->sockets))
+ ABORT(R_FAILED);
+
+ TAILQ_FOREACH(tcpsock, &sock->sockets, entry) {
+ if (nr_transport_addr_is_wildcard(&tcpsock->remote_addr))
+ continue;
+ r=nr_socket_recvfrom(tcpsock->inner, buf, maxlen, len, flags, from);
+ if (!r)
+ return 0;
+
+ if (r!=R_WOULDBLOCK) {
+ NR_SOCKET fd;
+ r_log(LOG_ICE,LOG_DEBUG,
+ "%s:%d function %s(to:%s) failed with error %d",__FILE__,
+ __LINE__,__FUNCTION__,tcpsock->remote_addr.as_string,r);
+ if (!nr_socket_getfd(tcpsock->inner, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+ }
+
+ TAILQ_REMOVE(&sock->sockets, tcpsock, entry);
+ nr_tcp_socket_ctx_destroy(&tcpsock);
+ ABORT(r);
+ }
+ }
+
+ /* this also gets returned if all tcpsocks have wildcard remote_addr */
+ _status=R_WOULDBLOCK;
+ abort:
+
+ return(_status);
+ }
+
+static int nr_socket_multi_tcp_getaddr(void *obj, nr_transport_addr *addrp)
+ {
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+
+ return nr_transport_addr_copy(addrp,&sock->addr);
+ }
+
+static int nr_socket_multi_tcp_close(void *obj)
+ {
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+ nr_tcp_socket_ctx *tcpsock;
+
+ if(sock->listen_socket)
+ nr_socket_close(sock->listen_socket);
+
+ TAILQ_FOREACH(tcpsock, &sock->sockets, entry) {
+ nr_socket_close(tcpsock->inner); //ignore errors
+ }
+
+ return 0;
+ }
+
+static void nr_tcp_socket_readable_cb(NR_SOCKET s, int how, void *arg)
+ {
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)arg;
+
+ // rearm
+ NR_ASYNC_WAIT(s, NR_ASYNC_WAIT_READ, nr_tcp_socket_readable_cb, arg);
+
+ if (sock->readable_cb)
+ sock->readable_cb(s, how, sock->readable_cb_arg);
+ }
+
+static int nr_socket_multi_tcp_connect(void *obj, nr_transport_addr *addr)
+ {
+ int r, _status;
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+ nr_socket *nrsock;
+
+ if ((r=nr_socket_multi_tcp_get_sock_connected_to(sock,addr,PREALLOC_CONNECT_FRAMED,&nrsock)))
+ ABORT(r);
+
+ _status=0;
+abort:
+ if (_status)
+ r_log(LOG_ICE,LOG_DEBUG,"%s:%d function %s(addr:%s) failed with error %d",__FILE__,__LINE__,__FUNCTION__,addr->as_string,_status);
+
+ return(_status);
+ }
+
+static void nr_tcp_multi_lsocket_readable_cb(NR_SOCKET s, int how, void *arg)
+ {
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)arg;
+ nr_socket *newsock;
+ nr_transport_addr remote_addr;
+ nr_tcp_socket_ctx *tcp_sock_ctx;
+ int r, _status;
+
+ // rearm
+ NR_ASYNC_WAIT(s, NR_ASYNC_WAIT_READ, nr_tcp_multi_lsocket_readable_cb, arg);
+
+ /* accept */
+ if ((r=nr_socket_accept(sock->listen_socket, &remote_addr, &newsock)))
+ ABORT(r);
+
+ /* This takes ownership of newsock whether it fails or not. */
+ if ((r=nr_tcp_socket_ctx_create(newsock, 1, sock->max_pending, &tcp_sock_ctx)))
+ ABORT(r);
+
+ nr_socket_buffered_set_connected_to(tcp_sock_ctx->inner, &remote_addr);
+
+ if ((r=nr_tcp_socket_ctx_initialize(tcp_sock_ctx, &remote_addr, sock))) {
+ nr_tcp_socket_ctx_destroy(&tcp_sock_ctx);
+ ABORT(r);
+ }
+
+ TAILQ_INSERT_HEAD(&sock->sockets, tcp_sock_ctx, entry);
+
+ _status=0;
+abort:
+ if (_status) {
+ r_log(LOG_ICE,LOG_WARNING,"%s:%d %s failed to accept new TCP connection: %d",__FILE__,__LINE__,__FUNCTION__,_status);
+ } else {
+ r_log(LOG_ICE,LOG_INFO,"%s:%d %s accepted new TCP connection from %s",__FILE__,__LINE__,__FUNCTION__,remote_addr.as_string);
+ }
+ }
+
+static int nr_socket_multi_tcp_listen(void *obj, int backlog)
+ {
+ int r, _status;
+ nr_socket_multi_tcp *sock=(nr_socket_multi_tcp *)obj;
+ NR_SOCKET fd;
+
+ if(!sock->listen_socket)
+ ABORT(R_FAILED);
+
+ if ((r=nr_socket_listen(sock->listen_socket, backlog)))
+ ABORT(r);
+
+ if ((r=nr_socket_getfd(sock->listen_socket, &fd)))
+ ABORT(r);
+
+ NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, nr_tcp_multi_lsocket_readable_cb, sock);
+
+ _status=0;
+ abort:
+ if (_status)
+ r_log(LOG_ICE,LOG_WARNING,"%s:%d function %s failed with error %d",__FILE__,__LINE__,__FUNCTION__,_status);
+
+ return(_status);
+ }
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.h b/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.h
new file mode 100644
index 000000000..a99e1652d
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket_multi_tcp.h
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2014, Mozilla
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _nr_socket_multi_tcp_h
+#define _nr_socket_multi_tcp_h
+
+#include "nr_socket.h"
+
+/* Argument use_framing is 0 only in call from test code (STUN TCP server
+ listening socket). For other purposes it should be always set to true */
+
+int nr_socket_multi_tcp_create(struct nr_ice_ctx_ *ctx,
+ nr_transport_addr *addr, nr_socket_tcp_type tcp_type,
+ int precreated_so_count, int max_pending, nr_socket **sockp);
+
+int nr_socket_multi_tcp_set_readable_cb(nr_socket *sock,
+ NR_async_cb readable_cb,void *readable_cb_arg);
+
+int nr_socket_multi_tcp_stun_server_connect(nr_socket *sock,
+ nr_transport_addr *addr);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.c b/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.c
new file mode 100644
index 000000000..0c9ec5674
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.c
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <nr_api.h>
+#include "nr_socket_wrapper.h"
+
+int nr_socket_wrapper_factory_create_int(void *obj, nr_socket_wrapper_factory_vtbl *vtbl,
+ nr_socket_wrapper_factory **wrapperp)
+{
+ int _status;
+ nr_socket_wrapper_factory *wrapper=0;
+
+ if (!(wrapper=RCALLOC(sizeof(nr_socket_wrapper_factory))))
+ ABORT(R_NO_MEMORY);
+
+ wrapper->obj=obj;
+ wrapper->vtbl=vtbl;
+
+ *wrapperp=wrapper;
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_socket_wrapper_factory_wrap(nr_socket_wrapper_factory *wrapper,
+ nr_socket *inner,
+ nr_socket **socketp)
+{
+ return wrapper->vtbl->wrap(wrapper->obj, inner, socketp);
+}
+
+int nr_socket_wrapper_factory_destroy(nr_socket_wrapper_factory **wrapperp)
+{
+ nr_socket_wrapper_factory *wrapper;
+
+ if (!wrapperp || !*wrapperp)
+ return 0;
+
+ wrapper = *wrapperp;
+ *wrapperp = 0;
+
+ assert(wrapper->vtbl);
+ if (wrapper->vtbl)
+ wrapper->vtbl->destroy(&wrapper->obj);
+
+ RFREE(wrapper);
+
+ return 0;
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.h b/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.h
new file mode 100644
index 000000000..717518e23
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/nr_socket_wrapper.h
@@ -0,0 +1,63 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _nr_socket_wrapper_h
+#define _nr_socket_wrapper_h
+
+#include "nr_socket.h"
+
+typedef struct nr_socket_wrapper_factory_vtbl_ {
+ int (*wrap)(void *obj,
+ nr_socket *socket,
+ nr_socket **socketp);
+ int (*destroy)(void **obj);
+} nr_socket_wrapper_factory_vtbl;
+
+typedef struct nr_socket_wrapper_factory_ {
+ void *obj;
+ nr_socket_wrapper_factory_vtbl *vtbl;
+} nr_socket_wrapper_factory;
+
+
+int nr_socket_wrapper_factory_create_int(void *obj, nr_socket_wrapper_factory_vtbl *vtbl,
+ nr_socket_wrapper_factory **wrapperp);
+
+
+int nr_socket_wrapper_factory_wrap(nr_socket_wrapper_factory *wrapper, nr_socket *inner,
+ nr_socket **socketp);
+
+int nr_socket_wrapper_factory_destroy(nr_socket_wrapper_factory **wrapperp);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.c b/media/mtransport/third_party/nICEr/src/net/transport_addr.c
new file mode 100644
index 000000000..b44ad5b2c
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.c
@@ -0,0 +1,476 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: transport_addr.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
+
+
+#include <csi_platform.h>
+#include <stdio.h>
+#include <memory.h>
+#include <sys/types.h>
+#include <errno.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <assert.h>
+#include "nr_api.h"
+#include "util.h"
+#include "transport_addr.h"
+
+int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr)
+ {
+ int _status;
+ /* Max length for normalized IPv6 address string representation is 39 */
+ char buffer[40];
+ const char *protocol;
+
+ switch(addr->protocol){
+ case IPPROTO_TCP:
+ protocol = "TCP";
+ break;
+ case IPPROTO_UDP:
+ protocol = "UDP";
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ switch(addr->ip_version){
+ case NR_IPV4:
+ if (!inet_ntop(AF_INET, &addr->u.addr4.sin_addr,buffer,sizeof(buffer)))
+ strcpy(buffer, "[error]");
+ snprintf(addr->as_string,sizeof(addr->as_string),"IP4:%s:%d/%s",buffer,(int)ntohs(addr->u.addr4.sin_port),protocol);
+ break;
+ case NR_IPV6:
+ if (!inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,buffer,sizeof(buffer)))
+ strcpy(buffer, "[error]");
+ snprintf(addr->as_string,sizeof(addr->as_string),"IP6:[%s]:%d/%s",buffer,(int)ntohs(addr->u.addr6.sin6_port),protocol);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char *buf, int len)
+ {
+ int _status;
+ char buffer[40];
+
+ switch(addr->ip_version){
+ case NR_IPV4:
+ if (!inet_ntop(AF_INET, &addr->u.addr4.sin_addr,buffer,sizeof(buffer))) {
+ strncpy(buffer, "[error]", len);
+ }
+ break;
+ case NR_IPV6:
+ if (!inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,buffer,sizeof(buffer))) {
+ strncpy(buffer, "[error]", len);
+ }
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+ snprintf(buf,len,"%s:%s",addr->ifname,buffer);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int protocol, int keep, nr_transport_addr *addr)
+ {
+ int r,_status;
+
+ if(!keep) memset(addr,0,sizeof(nr_transport_addr));
+
+ switch(protocol){
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ break;
+ default:
+ ABORT(R_BAD_ARGS);
+ }
+
+ addr->protocol=protocol;
+
+ if(saddr->sa_family==AF_INET){
+ addr->ip_version=NR_IPV4;
+
+ memcpy(&addr->u.addr4,saddr,sizeof(struct sockaddr_in));
+ addr->addr=(struct sockaddr *)&addr->u.addr4;
+ addr->addr_len=sizeof(struct sockaddr_in);
+ }
+ else if(saddr->sa_family==AF_INET6){
+ addr->ip_version=NR_IPV6;
+
+ memcpy(&addr->u.addr6, saddr, sizeof(struct sockaddr_in6));
+ addr->addr=(struct sockaddr *)&addr->u.addr6;
+ addr->addr_len=sizeof(struct sockaddr_in6);
+ }
+ else
+ ABORT(R_BAD_ARGS);
+
+ if(r=nr_transport_addr_fmt_addr_string(addr))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from)
+ {
+ memcpy(to,from,sizeof(nr_transport_addr));
+ to->addr=(struct sockaddr *)((char *)to + ((char *)from->addr - (char *)from));
+
+ return(0);
+ }
+
+int nr_transport_addr_copy_keep_ifname(nr_transport_addr *to, nr_transport_addr *from)
+ {
+ int r,_status;
+ char save_ifname[MAXIFNAME];
+
+ strncpy(save_ifname, to->ifname, MAXIFNAME);
+ save_ifname[MAXIFNAME-1]=0; /* Ensure null termination */
+
+ if (r=nr_transport_addr_copy(to, from))
+ ABORT(r);
+
+ strncpy(to->ifname, save_ifname, MAXIFNAME);
+
+ if (r=nr_transport_addr_fmt_addr_string(to))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return _status;
+ }
+
+/* Convenience fxn. Is this the right API?*/
+int nr_ip4_port_to_transport_addr(UINT4 ip4, UINT2 port, int protocol, nr_transport_addr *addr)
+ {
+ int r,_status;
+
+ memset(addr, 0, sizeof(nr_transport_addr));
+
+ addr->ip_version=NR_IPV4;
+ addr->protocol=protocol;
+#ifdef HAVE_SIN_LEN
+ addr->u.addr4.sin_len=sizeof(struct sockaddr_in);
+#endif
+ addr->u.addr4.sin_family=PF_INET;
+ addr->u.addr4.sin_port=htons(port);
+ addr->u.addr4.sin_addr.s_addr=htonl(ip4);
+ addr->addr=(struct sockaddr *)&addr->u.addr4;
+ addr->addr_len=sizeof(struct sockaddr_in);
+
+ if(r=nr_transport_addr_fmt_addr_string(addr))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_str_port_to_transport_addr(const char *ip, UINT2 port, int protocol, nr_transport_addr *addr_out)
+ {
+ int r,_status;
+ struct in_addr addr;
+ struct in6_addr addr6;
+
+ if (inet_pton(AF_INET, ip, &addr) == 1) {
+ if(r=nr_ip4_port_to_transport_addr(ntohl(addr.s_addr),port,protocol,addr_out))
+ ABORT(r);
+ } else if (inet_pton(AF_INET6, ip, &addr6) == 1) {
+ if(r=nr_ip6_port_to_transport_addr(&addr6,port,protocol,addr_out))
+ ABORT(r);
+ } else {
+ ABORT(R_BAD_DATA);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_ip6_port_to_transport_addr(struct in6_addr* addr6, UINT2 port, int protocol, nr_transport_addr *addr)
+ {
+ int r,_status;
+
+ memset(addr, 0, sizeof(nr_transport_addr));
+
+ addr->ip_version=NR_IPV6;
+ addr->protocol=protocol;
+ addr->u.addr6.sin6_family=PF_INET6;
+ addr->u.addr6.sin6_port=htons(port);
+ memcpy(addr->u.addr6.sin6_addr.s6_addr, addr6->s6_addr, sizeof(addr6->s6_addr));
+ addr->addr=(struct sockaddr *)&addr->u.addr6;
+ addr->addr_len=sizeof(struct sockaddr_in6);
+
+ if(r=nr_transport_addr_fmt_addr_string(addr))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_transport_addr_get_addrstring(const nr_transport_addr *addr, char *str, int maxlen)
+ {
+ int _status;
+ const char *res;
+
+ switch(addr->ip_version){
+ case NR_IPV4:
+ res = inet_ntop(AF_INET, &addr->u.addr4.sin_addr,str,maxlen);
+ break;
+ case NR_IPV6:
+ res = inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,str,maxlen);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ if(!res){
+ if (errno == ENOSPC){
+ ABORT(R_BAD_ARGS);
+ }
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_transport_addr_get_port(nr_transport_addr *addr, int *port)
+ {
+ int _status;
+
+ switch(addr->ip_version){
+ case NR_IPV4:
+ *port=ntohs(addr->u.addr4.sin_port);
+ break;
+ case NR_IPV6:
+ *port=ntohs(addr->u.addr6.sin6_port);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_transport_addr_set_port(nr_transport_addr *addr, int port)
+ {
+ int _status;
+
+ switch(addr->ip_version){
+ case NR_IPV4:
+ addr->u.addr4.sin_port=htons(port);
+ break;
+ case NR_IPV6:
+ addr->u.addr6.sin6_port=htons(port);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* memcmp() may not work if, for instance, the string or interface
+ haven't been made. Hmmm.. */
+int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int mode)
+ {
+ assert(mode);
+
+ if(addr1->ip_version != addr2->ip_version)
+ return(1);
+
+ if(mode < NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL)
+ return(0);
+
+ if(addr1->protocol != addr2->protocol)
+ return(1);
+
+ if(mode < NR_TRANSPORT_ADDR_CMP_MODE_ADDR)
+ return(0);
+
+ assert(addr1->addr_len == addr2->addr_len);
+ switch(addr1->ip_version){
+ case NR_IPV4:
+ if(addr1->u.addr4.sin_addr.s_addr != addr2->u.addr4.sin_addr.s_addr)
+ return(1);
+ if(mode < NR_TRANSPORT_ADDR_CMP_MODE_ALL)
+ return(0);
+ if(addr1->u.addr4.sin_port != addr2->u.addr4.sin_port)
+ return(1);
+ break;
+ case NR_IPV6:
+ if(memcmp(addr1->u.addr6.sin6_addr.s6_addr,addr2->u.addr6.sin6_addr.s6_addr,sizeof(struct in6_addr)))
+ return(1);
+ if(mode < NR_TRANSPORT_ADDR_CMP_MODE_ALL)
+ return(0);
+ if(addr1->u.addr6.sin6_port != addr2->u.addr6.sin6_port)
+ return(1);
+ break;
+ default:
+ abort();
+ }
+
+ return(0);
+ }
+
+int nr_transport_addr_is_loopback(nr_transport_addr *addr)
+ {
+ switch(addr->ip_version){
+ case NR_IPV4:
+ switch(addr->u.addr4.sin_family){
+ case AF_INET:
+ if (((ntohl(addr->u.addr4.sin_addr.s_addr)>>24)&0xff)==0x7f)
+ return 1;
+ break;
+ default:
+ UNIMPLEMENTED;
+ break;
+ }
+ break;
+
+ case NR_IPV6:
+ if(!memcmp(addr->u.addr6.sin6_addr.s6_addr,in6addr_loopback.s6_addr,sizeof(struct in6_addr)))
+ return(1);
+ break;
+ default:
+ UNIMPLEMENTED;
+ }
+
+ return(0);
+ }
+
+int nr_transport_addr_is_link_local(nr_transport_addr *addr)
+ {
+ switch(addr->ip_version){
+ case NR_IPV4:
+ /* RFC3927: 169.254/16 */
+ if ((ntohl(addr->u.addr4.sin_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000)
+ return(1);
+ break;
+ case NR_IPV6:
+ {
+ UINT4* addrTop = (UINT4*)(addr->u.addr6.sin6_addr.s6_addr);
+ if ((*addrTop & htonl(0xFFC00000)) == htonl(0xFE800000))
+ return(2);
+ }
+ break;
+ default:
+ UNIMPLEMENTED;
+ }
+
+ return(0);
+ }
+
+int nr_transport_addr_is_wildcard(nr_transport_addr *addr)
+ {
+ switch(addr->ip_version){
+ case NR_IPV4:
+ if(addr->u.addr4.sin_addr.s_addr==INADDR_ANY)
+ return(1);
+ if(addr->u.addr4.sin_port==0)
+ return(1);
+ break;
+ case NR_IPV6:
+ if(!memcmp(addr->u.addr6.sin6_addr.s6_addr,in6addr_any.s6_addr,sizeof(struct in6_addr)))
+ return(1);
+ if(addr->u.addr6.sin6_port==0)
+ return(1);
+ break;
+ default:
+ UNIMPLEMENTED;
+ }
+
+ return(0);
+ }
+
+nr_transport_addr_mask nr_private_ipv4_addrs[] = {
+ /* RFC1918: 10/8 */
+ {0x0A000000, 0xFF000000},
+ /* RFC1918: 172.16/12 */
+ {0xAC100000, 0xFFF00000},
+ /* RFC1918: 192.168/16 */
+ {0xC0A80000, 0xFFFF0000},
+ /* RFC6598: 100.64/10 */
+ {0x64400000, 0xFFC00000}
+};
+
+int nr_transport_addr_get_private_addr_range(nr_transport_addr *addr)
+ {
+ switch(addr->ip_version){
+ case NR_IPV4:
+ {
+ UINT4 ip = ntohl(addr->u.addr4.sin_addr.s_addr);
+ for (int i=0; i<(sizeof(nr_private_ipv4_addrs)/sizeof(nr_transport_addr_mask)); i++) {
+ if ((ip & nr_private_ipv4_addrs[i].mask) == nr_private_ipv4_addrs[i].addr)
+ return i + 1;
+ }
+ }
+ break;
+ case NR_IPV6:
+ return(0);
+ default:
+ UNIMPLEMENTED;
+ }
+
+ return(0);
+ }
+
+int nr_transport_addr_is_reliable_transport(nr_transport_addr *addr)
+ {
+ return addr->protocol == IPPROTO_TCP;
+ }
diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.h b/media/mtransport/third_party/nICEr/src/net/transport_addr.h
new file mode 100644
index 000000000..dfec63329
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _transport_addr_h
+#define _transport_addr_h
+
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+/* Length of a string hex representation of a MD5 hash */
+#define MAXIFNAME 33
+
+/* Generic transport address
+
+ This spans both sockaddr_in and sockaddr_in6
+ */
+typedef struct nr_transport_addr_ {
+ UCHAR ip_version; /* 4 or 6 */
+#define NR_IPV4 4
+#define NR_IPV6 6
+ UCHAR protocol; /* IPPROTO_TCP, IPPROTO_UDP */
+ struct sockaddr *addr;
+ int addr_len;
+ union {
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ } u;
+ char ifname[MAXIFNAME];
+ /* A string version.
+ 56 = 5 ("IP6:[") + 39 (ipv6 address) + 2 ("]:") + 5 (port) + 4 (/UDP) + 1 (null) */
+ char as_string[56];
+} nr_transport_addr;
+
+typedef struct nr_transport_addr_mask_ {
+ UINT4 addr;
+ UINT4 mask;
+} nr_transport_addr_mask;
+
+int nr_sockaddr_to_transport_addr(struct sockaddr *saddr, int protocol, int keep, nr_transport_addr *addr);
+
+// addresses, ports in local byte order
+int nr_ip4_port_to_transport_addr(UINT4 ip4, UINT2 port, int protocol, nr_transport_addr *addr);
+int nr_str_port_to_transport_addr(const char *str, UINT2 port, int protocol, nr_transport_addr *addr);
+int nr_ip6_port_to_transport_addr(struct in6_addr* addr6, UINT2 port, int protocol, nr_transport_addr *addr);
+
+int nr_transport_addr_get_addrstring(const nr_transport_addr *addr, char *str, int maxlen);
+int nr_transport_addr_get_port(nr_transport_addr *addr, int *port);
+int nr_transport_addr_cmp(nr_transport_addr *addr1,nr_transport_addr *addr2,int mode);
+#define NR_TRANSPORT_ADDR_CMP_MODE_VERSION 1
+#define NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL 2
+#define NR_TRANSPORT_ADDR_CMP_MODE_ADDR 3
+#define NR_TRANSPORT_ADDR_CMP_MODE_ALL 4
+
+int nr_transport_addr_is_wildcard(nr_transport_addr *addr);
+int nr_transport_addr_is_loopback(nr_transport_addr *addr);
+int nr_transport_addr_get_private_addr_range(nr_transport_addr *addr);
+int nr_transport_addr_is_link_local(nr_transport_addr *addr);
+int nr_transport_addr_copy(nr_transport_addr *to, nr_transport_addr *from);
+int nr_transport_addr_copy_keep_ifname(nr_transport_addr *to, nr_transport_addr *from);
+int nr_transport_addr_fmt_addr_string(nr_transport_addr *addr);
+int nr_transport_addr_fmt_ifname_addr_string(const nr_transport_addr *addr, char *buf, int len);
+int nr_transport_addr_set_port(nr_transport_addr *addr, int port);
+int nr_transport_addr_is_reliable_transport(nr_transport_addr *addr);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c
new file mode 100644
index 000000000..6a8a64bb9
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.c
@@ -0,0 +1,233 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
+
+#include <csi_platform.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/types.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <strings.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <assert.h>
+#include "nr_api.h"
+#include "util.h"
+#include "transport_addr.h"
+#include "transport_addr_reg.h"
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46 /* Value used by linux/BSD */
+#endif
+
+int
+nr_reg_get_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr)
+{
+ int r,_status;
+ unsigned int count;
+ char *address = 0;
+ UINT2 port = 0;
+ char *ifname = 0;
+ char *protocol = 0;
+ int p;
+
+ if ((r=NR_reg_get_child_count(prefix, &count)))
+ ABORT(r);
+
+ if (count == 0)
+ ABORT(R_NOT_FOUND);
+
+ if ((r=NR_reg_alloc2_string(prefix, "address", &address))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ address = 0;
+ }
+
+ if ((r=NR_reg_alloc2_string(prefix, "ifname", &ifname))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ ifname = 0;
+ }
+
+ if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ port = 0;
+ }
+
+ if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ p = IPPROTO_UDP;
+
+ protocol = 0;
+ }
+ else {
+ if (!strcasecmp("tcp", protocol))
+ p = IPPROTO_TCP;
+ else if (!strcasecmp("udp", protocol))
+ p = IPPROTO_UDP;
+ else
+ ABORT(R_BAD_DATA);
+ }
+
+ if (!keep) memset(addr, 0, sizeof(*addr));
+
+ if ((r=nr_str_port_to_transport_addr(address?address:"0.0.0.0", port, p, addr)))
+ ABORT(r);
+
+ if (ifname)
+ strlcpy(addr->ifname, ifname, sizeof(addr->ifname));
+
+ _status=0;
+ abort:
+ RFREE(protocol);
+ RFREE(ifname);
+ RFREE(address);
+ return(_status);
+}
+
+int
+nr_reg_set_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr)
+{
+ int r,_status;
+
+ if (! keep) {
+ if ((r=NR_reg_del(prefix)))
+ ABORT(r);
+ }
+
+ switch (addr->ip_version) {
+ case NR_IPV4:
+ if (!nr_transport_addr_is_wildcard(addr)) {
+ if ((r=NR_reg_set2_string(prefix, "address", inet_ntoa(addr->u.addr4.sin_addr))))
+ ABORT(r);
+ }
+
+ if (addr->u.addr4.sin_port != 0) {
+ if ((r=NR_reg_set2_uint2(prefix, "port", ntohs(addr->u.addr4.sin_port))))
+ ABORT(r);
+ }
+ break;
+
+ case NR_IPV6:
+ if (!nr_transport_addr_is_wildcard(addr)) {
+ char address[INET6_ADDRSTRLEN];
+ if(!inet_ntop(AF_INET6, &addr->u.addr6.sin6_addr,address,sizeof(address))) {
+ ABORT(R_BAD_DATA);
+ }
+
+ if ((r=NR_reg_set2_string(prefix, "address", address))) {
+ ABORT(r);
+ }
+ }
+
+ if (addr->u.addr6.sin6_port != 0) {
+ if ((r=NR_reg_set2_uint2(prefix, "port", ntohs(addr->u.addr6.sin6_port))))
+ ABORT(r);
+ }
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ /* We abort if neither NR_IPV4 or NR_IPV6 above */
+ switch (addr->protocol) {
+ case IPPROTO_TCP:
+ if ((r=NR_reg_set2_string(prefix, "protocol", "tcp")))
+ ABORT(r);
+ break;
+ case IPPROTO_UDP:
+ if ((r=NR_reg_set2_string(prefix, "protocol", "udp")))
+ ABORT(r);
+ break;
+ default:
+ UNIMPLEMENTED;
+ break;
+ }
+
+ if (strlen(addr->ifname) > 0) {
+ if ((r=NR_reg_set2_string(prefix, "ifname", addr->ifname)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (_status)
+ NR_reg_del(prefix);
+ return _status;
+}
+
+int
+nr_reg_get_transport_addr2(NR_registry prefix, char *name, int keep, nr_transport_addr *addr)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=NR_reg_make_registry(prefix, name, registry)))
+ ABORT(r);
+
+ if ((r=nr_reg_get_transport_addr(registry, keep, addr)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return _status;
+}
+
+int
+nr_reg_set_transport_addr2(NR_registry prefix, char *name, int keep, nr_transport_addr *addr)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=NR_reg_make_registry(prefix, name, registry)))
+ ABORT(r);
+
+ if ((r=nr_reg_set_transport_addr(registry, keep, addr)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return _status;
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.h b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.h
new file mode 100644
index 000000000..761953a9c
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/net/transport_addr_reg.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _transport_addr_reg_h
+#define _transport_addr_reg_h
+
+#include "registry.h"
+
+int nr_reg_get_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr);
+int nr_reg_set_transport_addr(NR_registry prefix, int keep, nr_transport_addr *addr);
+int nr_reg_get_transport_addr2(NR_registry prefix, char *name, int keep, nr_transport_addr *addr);
+int nr_reg_set_transport_addr2(NR_registry prefix, char *name, int keep, nr_transport_addr *addr);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/addrs.c b/media/mtransport/third_party/nICEr/src/stun/addrs.c
new file mode 100644
index 000000000..c90191f73
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/addrs.c
@@ -0,0 +1,444 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: addrs.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <csi_platform.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <tchar.h>
+#else /* !WIN32 */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#ifndef ANDROID
+/* This works on linux and BSD, but not android */
+#include <sys/types.h> /* getifaddrs */
+#include <ifaddrs.h> /* getifaddrs */
+#else
+#include "ifaddrs-android.h"
+#define getifaddrs android_getifaddrs
+#define freeifaddrs android_freeifaddrs
+#endif
+
+#ifdef LINUX
+
+#ifdef ANDROID
+/* Work around an Android NDK < r8c bug */
+#undef __unused
+#else
+#include <linux/if.h> /* struct ifreq, IFF_POINTTOPOINT */
+#include <linux/wireless.h> /* struct iwreq */
+#include <linux/ethtool.h> /* struct ethtool_cmd */
+#include <linux/sockios.h> /* SIOCETHTOOL */
+#endif /* ANDROID */
+
+#endif /* LINUX */
+
+#endif /* !WIN32 */
+
+#include "stun.h"
+#include "addrs.h"
+#include "nr_crypto.h"
+#include "util.h"
+
+#if defined(WIN32)
+
+#define WIN32_MAX_NUM_INTERFACES 20
+
+#define NR_MD5_HASH_LENGTH 16
+
+#define _NR_MAX_KEY_LENGTH 256
+#define _NR_MAX_NAME_LENGTH 512
+
+#define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
+{
+ int r,_status;
+ HKEY adapter_reg;
+ TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
+ TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
+ TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
+ DWORD keyval_len, key_type;
+ size_t converted_chars, newlen;
+ char *my_fn = 0;
+
+#ifdef _UNICODE
+ mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
+ adapter_GUID, _TRUNCATE);
+#else
+ strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
+#endif
+
+ _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
+ _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
+ _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
+ _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));
+
+ r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);
+
+ if (r != ERROR_SUCCESS) {
+ r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
+ ABORT(R_INTERNAL);
+ }
+
+ keyval_len = sizeof(keyval_buf);
+ r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
+ (BYTE *)keyval_buf, &keyval_len);
+
+ RegCloseKey(adapter_reg);
+
+#ifdef UNICODE
+ newlen = wcslen(keyval_buf)+1;
+ my_fn = (char *) RCALLOC(newlen);
+ if (!my_fn) {
+ ABORT(R_NO_MEMORY);
+ }
+ wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
+#else
+ my_fn = r_strdup(keyval_buf);
+#endif
+
+ *friendly_name = my_fn;
+ _status=0;
+
+abort:
+ if (_status) {
+ if (my_fn) free(my_fn);
+ }
+ return(_status);
+}
+
+static int
+stun_get_win32_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
+{
+ int r, _status;
+ PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL;
+ // recomended per https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
+ static const ULONG initialBufLen = 15000;
+ ULONG buflen = initialBufLen;
+ char bin_hashed_ifname[NR_MD5_HASH_LENGTH];
+ char hex_hashed_ifname[MAXIFNAME];
+ int n = 0;
+
+ *count = 0;
+
+ if (maxaddrs <= 0)
+ ABORT(R_BAD_ARGS);
+
+ /* According to MSDN (see above) we have try GetAdapterAddresses() multiple times */
+ for (n = 0; n < 5; n++) {
+ AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen);
+ if (AdapterAddresses == NULL) {
+ r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()");
+ ABORT(R_NO_MEMORY);
+ }
+
+ r = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, AdapterAddresses, &buflen);
+ if (r == NO_ERROR) {
+ break;
+ }
+ r_log(NR_LOG_STUN, LOG_ERR, "GetAdaptersAddresses() returned error (%d)", r);
+ RFREE(AdapterAddresses);
+ AdapterAddresses = NULL;
+ }
+
+ if (n >= 5) {
+ r_log(NR_LOG_STUN, LOG_ERR, "5 failures calling GetAdaptersAddresses()");
+ ABORT(R_INTERNAL);
+ }
+
+ n = 0;
+
+ /* Loop through the adapters */
+
+ for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) {
+
+ if (tmpAddress->OperStatus != IfOperStatusUp)
+ continue;
+
+ if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) {
+ IP_ADAPTER_UNICAST_ADDRESS *u = 0;
+
+ if(r=nr_crypto_md5((UCHAR *)tmpAddress->FriendlyName,
+ wcslen(tmpAddress->FriendlyName) * sizeof(wchar_t),
+ bin_hashed_ifname))
+ ABORT(r);
+ if(r=nr_bin2hex(bin_hashed_ifname, sizeof(bin_hashed_ifname),
+ hex_hashed_ifname))
+ ABORT(r);
+
+ for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) {
+ SOCKET_ADDRESS *sa_addr = &u->Address;
+
+ if ((sa_addr->lpSockaddr->sa_family == AF_INET) ||
+ (sa_addr->lpSockaddr->sa_family == AF_INET6)) {
+ if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr))))
+ ABORT(r);
+ }
+ else {
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for address on adapter %lu", tmpAddress->IfIndex);
+ continue;
+ }
+
+ strlcpy(addrs[n].addr.ifname, hex_hashed_ifname, sizeof(addrs[n].addr.ifname));
+ if (tmpAddress->IfType == IF_TYPE_ETHERNET_CSMACD) {
+ addrs[n].interface.type = NR_INTERFACE_TYPE_WIRED;
+ } else if (tmpAddress->IfType == IF_TYPE_IEEE80211) {
+ /* Note: this only works for >= Win Vista */
+ addrs[n].interface.type = NR_INTERFACE_TYPE_WIFI;
+ } else {
+ addrs[n].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
+ }
+#if (_WIN32_WINNT >= 0x0600)
+ /* Note: only >= Vista provide link speed information */
+ addrs[n].interface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000;
+#else
+ addrs[n].interface.estimated_speed = 0;
+#endif
+ if (++n >= maxaddrs)
+ goto done;
+ }
+ }
+ }
+
+ done:
+ *count = n;
+ _status = 0;
+
+ abort:
+ RFREE(AdapterAddresses);
+ return _status;
+}
+
+#else /* WIN32 */
+
+static int
+nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr);
+
+static int
+stun_getifaddrs(nr_local_addr addrs[], int maxaddrs, int *count)
+{
+ int r,_status;
+ struct ifaddrs* if_addrs_head=NULL;
+ struct ifaddrs* if_addr;
+
+ *count = 0;
+
+ if (maxaddrs <= 0)
+ ABORT(R_BAD_ARGS);
+
+ if (getifaddrs(&if_addrs_head) == -1) {
+ r_log(NR_LOG_STUN, LOG_ERR, "getifaddrs error e = %d", errno);
+ ABORT(R_INTERNAL);
+ }
+
+ if_addr = if_addrs_head;
+
+ while (if_addr && *count < maxaddrs) {
+ /* This can be null */
+ if (if_addr->ifa_addr) {
+ switch (if_addr->ifa_addr->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ if (r=nr_sockaddr_to_transport_addr(if_addr->ifa_addr, IPPROTO_UDP, 0, &(addrs[*count].addr))) {
+ r_log(NR_LOG_STUN, LOG_ERR, "nr_sockaddr_to_transport_addr error r = %d", r);
+ } else {
+#if defined(LINUX) && !defined(ANDROID)
+ struct ethtool_cmd ecmd;
+ struct ifreq ifr;
+ struct iwreq wrq;
+ int e;
+ int s = socket(AF_INET, SOCK_DGRAM, 0);
+
+ strncpy(ifr.ifr_name, if_addr->ifa_name, sizeof(ifr.ifr_name));
+ /* TODO (Bug 896851): interface property for Android */
+ /* Getting ethtool for ethernet information. */
+ ecmd.cmd = ETHTOOL_GSET;
+ /* In/out param */
+ ifr.ifr_data = (void*)&ecmd;
+
+ e = ioctl(s, SIOCETHTOOL, &ifr);
+ if (e == 0)
+ {
+ /* For wireless network, we won't get ethtool, it's a wired
+ * connection */
+ addrs[*count].interface.type = NR_INTERFACE_TYPE_WIRED;
+#ifdef DONT_HAVE_ETHTOOL_SPEED_HI
+ addrs[*count].interface.estimated_speed = ecmd.speed;
+#else
+ addrs[*count].interface.estimated_speed = ((ecmd.speed_hi << 16) | ecmd.speed) * 1000;
+#endif
+ }
+
+ strncpy(wrq.ifr_name, if_addr->ifa_name, sizeof(wrq.ifr_name));
+ e = ioctl(s, SIOCGIWRATE, &wrq);
+ if (e == 0)
+ {
+ addrs[*count].interface.type = NR_INTERFACE_TYPE_WIFI;
+ addrs[*count].interface.estimated_speed = wrq.u.bitrate.value / 1000;
+ }
+
+ close(s);
+
+ if (if_addr->ifa_flags & IFF_POINTOPOINT)
+ {
+ addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN | NR_INTERFACE_TYPE_VPN;
+ /* TODO (Bug 896913): find backend network type of this VPN */
+ }
+#else
+ addrs[*count].interface.type = NR_INTERFACE_TYPE_UNKNOWN;
+ addrs[*count].interface.estimated_speed = 0;
+#endif
+ strlcpy(addrs[*count].addr.ifname, if_addr->ifa_name, sizeof(addrs[*count].addr.ifname));
+ ++(*count);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ if_addr = if_addr->ifa_next;
+ }
+
+ _status=0;
+abort:
+ if (if_addrs_head) {
+ freeifaddrs(if_addrs_head);
+ }
+ return(_status);
+}
+
+#endif
+
+static int
+nr_stun_is_duplicate_addr(nr_local_addr addrs[], int count, nr_local_addr *addr)
+{
+ int i;
+ int different;
+
+ for (i = 0; i < count; ++i) {
+ different = nr_transport_addr_cmp(&addrs[i].addr, &(addr->addr),
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL);
+ if (!different)
+ return 1; /* duplicate */
+ }
+
+ return 0;
+}
+
+int
+nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count)
+{
+ int r, _status;
+ nr_local_addr *tmp = 0;
+ int i;
+ int n;
+
+ tmp = RMALLOC(*count * sizeof(*tmp));
+ if (!tmp)
+ ABORT(R_NO_MEMORY);
+
+ n = 0;
+ for (i = 0; i < *count; ++i) {
+ if (nr_stun_is_duplicate_addr(tmp, n, &addrs[i])) {
+ /* skip addrs[i], it's a duplicate */
+ }
+ else if (remove_loopback && nr_transport_addr_is_loopback(&addrs[i].addr)) {
+ /* skip addrs[i], it's a loopback */
+ }
+ else if (remove_link_local &&
+ addrs[i].addr.ip_version == NR_IPV6 &&
+ nr_transport_addr_is_link_local(&addrs[i].addr)) {
+ /* skip addrs[i], it's a link-local address */
+ }
+ else {
+ /* otherwise, copy it to the temporary array */
+ if ((r=nr_local_addr_copy(&tmp[n], &addrs[i])))
+ ABORT(r);
+ ++n;
+ }
+ }
+
+ *count = n;
+
+ memset(addrs, 0, *count * sizeof(*addrs));
+ /* copy temporary array into passed in/out array */
+ for (i = 0; i < *count; ++i) {
+ if ((r=nr_local_addr_copy(&addrs[i], &tmp[i])))
+ ABORT(r);
+ }
+
+ _status = 0;
+ abort:
+ RFREE(tmp);
+ return _status;
+}
+
+#ifndef USE_PLATFORM_NR_STUN_GET_ADDRS
+
+int
+nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int drop_loopback, int drop_link_local, int *count)
+{
+ int r,_status=0;
+ int i;
+ char typestr[100];
+
+#ifdef WIN32
+ _status = stun_get_win32_addrs(addrs, maxaddrs, count);
+#else
+ _status = stun_getifaddrs(addrs, maxaddrs, count);
+#endif
+
+ if ((r=nr_stun_remove_duplicate_addrs(addrs, drop_loopback, drop_link_local, count)))
+ ABORT(r);
+
+ for (i = 0; i < *count; ++i) {
+ nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n",
+ i,addrs[i].addr.as_string,addrs[i].addr.ifname,typestr);
+ }
+
+abort:
+ return _status;
+}
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/stun/addrs.h b/media/mtransport/third_party/nICEr/src/stun/addrs.h
new file mode 100644
index 000000000..61a3496d1
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/addrs.h
@@ -0,0 +1,43 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _addrs_h_
+#define _addrs_h_
+
+#include "transport_addr.h"
+#include "local_addr.h"
+
+int nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int remove_loopback, int remove_link_local, int *count);
+int nr_stun_remove_duplicate_addrs(nr_local_addr addrs[], int remove_loopback, int remove_link_local, int *count);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c
new file mode 100644
index 000000000..d7d390f24
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.c
@@ -0,0 +1,242 @@
+/*
+Copyright (c) 2011, The WebRTC project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of Google nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#if defined(ANDROID)
+#include "ifaddrs-android.h"
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+struct netlinkrequest {
+ struct nlmsghdr header;
+ struct ifaddrmsg msg;
+};
+
+static const int kMaxReadSize = 4096;
+
+static int set_ifname(struct ifaddrs* ifaddr, int interface) {
+ char buf[IFNAMSIZ] = {0};
+ char* name = if_indextoname(interface, buf);
+ if (name == NULL) {
+ return -1;
+ }
+ ifaddr->ifa_name = malloc(strlen(name) + 1);
+ strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
+ return 0;
+}
+
+static int set_flags(struct ifaddrs* ifaddr) {
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
+ int rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
+ close(fd);
+ if (rc == -1) {
+ return -1;
+ }
+ ifaddr->ifa_flags = ifr.ifr_flags;
+ return 0;
+}
+
+static int set_addresses(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* data,
+ size_t len) {
+ if (msg->ifa_family == AF_INET) {
+ struct sockaddr_in* sa = malloc(sizeof(struct sockaddr_in));
+ memset(sa, 0, sizeof(struct sockaddr_in));
+ sa->sin_family = AF_INET;
+ memcpy(&sa->sin_addr, data, len);
+ ifaddr->ifa_addr = (struct sockaddr*)sa;
+ } else if (msg->ifa_family == AF_INET6) {
+ struct sockaddr_in6* sa = malloc(sizeof(struct sockaddr_in6));
+ memset(sa, 0, sizeof(struct sockaddr_in6));
+ sa->sin6_family = AF_INET6;
+ sa->sin6_scope_id = msg->ifa_index;
+ memcpy(&sa->sin6_addr, data, len);
+ ifaddr->ifa_addr = (struct sockaddr*)sa;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) {
+ char* prefix = NULL;
+ if (family == AF_INET) {
+ struct sockaddr_in* mask = malloc(sizeof(struct sockaddr_in));
+ memset(mask, 0, sizeof(struct sockaddr_in));
+ mask->sin_family = AF_INET;
+ memset(&mask->sin_addr, 0, sizeof(struct in_addr));
+ ifaddr->ifa_netmask = (struct sockaddr*)mask;
+ if (prefixlen > 32) {
+ prefixlen = 32;
+ }
+ prefix = (char*)&mask->sin_addr;
+ } else if (family == AF_INET6) {
+ struct sockaddr_in6* mask = malloc(sizeof(struct sockaddr_in6));
+ memset(mask, 0, sizeof(struct sockaddr_in6));
+ mask->sin6_family = AF_INET6;
+ memset(&mask->sin6_addr, 0, sizeof(struct in6_addr));
+ ifaddr->ifa_netmask = (struct sockaddr*)mask;
+ if (prefixlen > 128) {
+ prefixlen = 128;
+ }
+ prefix = (char*)&mask->sin6_addr;
+ } else {
+ return -1;
+ }
+ for (int i = 0; i < (prefixlen / 8); i++) {
+ *prefix++ = 0xFF;
+ }
+ char remainder = 0xff;
+ remainder <<= (8 - prefixlen % 8);
+ *prefix = remainder;
+ return 0;
+}
+
+static int populate_ifaddrs(struct ifaddrs* ifaddr, struct ifaddrmsg* msg, void* bytes,
+ size_t len) {
+ if (set_ifname(ifaddr, msg->ifa_index) != 0) {
+ return -1;
+ }
+ if (set_flags(ifaddr) != 0) {
+ return -1;
+ }
+ if (set_addresses(ifaddr, msg, bytes, len) != 0) {
+ return -1;
+ }
+ if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int android_getifaddrs(struct ifaddrs** result) {
+ int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0) {
+ return -1;
+ }
+
+ struct netlinkrequest ifaddr_request;
+ memset(&ifaddr_request, 0, sizeof(ifaddr_request));
+ ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
+ ifaddr_request.header.nlmsg_type = RTM_GETADDR;
+ ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+
+ ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0);
+ if ((size_t)count != ifaddr_request.header.nlmsg_len) {
+ close(fd);
+ return -1;
+ }
+ struct ifaddrs* start = NULL;
+ struct ifaddrs* current = NULL;
+ char buf[kMaxReadSize];
+ ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ while (amount_read > 0) {
+ struct nlmsghdr* header = (struct nlmsghdr*)&buf[0];
+ size_t header_size = (size_t)amount_read;
+ for ( ; NLMSG_OK(header, header_size);
+ header = NLMSG_NEXT(header, header_size)) {
+ switch (header->nlmsg_type) {
+ case NLMSG_DONE:
+ /* Success. Return. */
+ *result = start;
+ close(fd);
+ return 0;
+ case NLMSG_ERROR:
+ close(fd);
+ android_freeifaddrs(start);
+ return -1;
+ case RTM_NEWADDR: {
+ struct ifaddrmsg* address_msg =
+ (struct ifaddrmsg*)NLMSG_DATA(header);
+ struct rtattr* rta = IFA_RTA(address_msg);
+ ssize_t payload_len = IFA_PAYLOAD(header);
+ while (RTA_OK(rta, payload_len)) {
+ if (rta->rta_type == IFA_ADDRESS) {
+ int family = address_msg->ifa_family;
+ if (family == AF_INET || family == AF_INET6) {
+ struct ifaddrs* newest = malloc(sizeof(struct ifaddrs));
+ memset(newest, 0, sizeof(struct ifaddrs));
+ if (current) {
+ current->ifa_next = newest;
+ } else {
+ start = newest;
+ }
+ if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta),
+ RTA_PAYLOAD(rta)) != 0) {
+ android_freeifaddrs(start);
+ *result = NULL;
+ return -1;
+ }
+ current = newest;
+ }
+ }
+ rta = RTA_NEXT(rta, payload_len);
+ }
+ break;
+ }
+ }
+ }
+ amount_read = recv(fd, &buf, kMaxReadSize, 0);
+ }
+ close(fd);
+ android_freeifaddrs(start);
+ return -1;
+}
+
+void android_freeifaddrs(struct ifaddrs* addrs) {
+ struct ifaddrs* last = NULL;
+ struct ifaddrs* cursor = addrs;
+ while (cursor) {
+ free(cursor->ifa_name);
+ free(cursor->ifa_addr);
+ free(cursor->ifa_netmask);
+ last = cursor;
+ cursor = cursor->ifa_next;
+ free(last);
+ }
+}
+
+#endif /* defined(ANDROID) */
diff --git a/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h
new file mode 100644
index 000000000..5ba174ce6
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/ifaddrs-android.h
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2011, The WebRTC project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of Google nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef WEBRTC_BASE_IFADDRS_ANDROID_H_
+#define WEBRTC_BASE_IFADDRS_ANDROID_H_
+
+#include <stdio.h>
+#include <sys/socket.h>
+
+/* Implementation of getifaddrs for Android.
+ * Fills out a list of ifaddr structs (see below) which contain information
+ * about every network interface available on the host.
+ * See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function). */
+struct ifaddrs {
+ struct ifaddrs* ifa_next;
+ char* ifa_name;
+ unsigned int ifa_flags;
+ struct sockaddr* ifa_addr;
+ struct sockaddr* ifa_netmask;
+ /* Real ifaddrs has broadcast, point to point and data members.
+ * We don't need them (yet?). */
+};
+
+int android_getifaddrs(struct ifaddrs** result);
+void android_freeifaddrs(struct ifaddrs* addrs);
+
+#endif /* WEBRTC_BASE_IFADDRS_ANDROID_H_ */
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c b/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
new file mode 100644
index 000000000..c82c545f3
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
@@ -0,0 +1,610 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <nr_api.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#include "p_buf.h"
+#include "nr_socket.h"
+#include "stun.h"
+#include "nr_socket_buffered_stun.h"
+
+#define NR_MAX_FRAME_SIZE 0xFFFF
+
+typedef struct nr_frame_header_ {
+ UINT2 frame_length;
+ char data[0];
+} nr_frame_header;
+
+typedef struct nr_socket_buffered_stun_ {
+ nr_socket *inner;
+ nr_transport_addr remote_addr;
+ int connected;
+
+ /* Read state */
+ int read_state;
+#define NR_ICE_SOCKET_READ_NONE 0
+#define NR_ICE_SOCKET_READ_HDR 1
+#define NR_ICE_SOCKET_READ_FAILED 2
+ UCHAR *buffer;
+ size_t buffer_size;
+ size_t bytes_needed;
+ size_t bytes_read;
+ NR_async_cb readable_cb;
+ void *readable_cb_arg;
+
+ /* Write state */
+ nr_p_buf_ctx *p_bufs;
+ nr_p_buf_head pending_writes;
+ size_t pending;
+ size_t max_pending;
+ nr_framing_type framing_type;
+} nr_socket_buffered_stun;
+
+static int nr_socket_buffered_stun_destroy(void **objp);
+static int nr_socket_buffered_stun_sendto(void *obj,const void *msg, size_t len,
+ int flags, nr_transport_addr *to);
+static int nr_socket_buffered_stun_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *from);
+static int nr_socket_buffered_stun_getfd(void *obj, NR_SOCKET *fd);
+static int nr_socket_buffered_stun_getaddr(void *obj, nr_transport_addr *addrp);
+static int nr_socket_buffered_stun_close(void *obj);
+static int nr_socket_buffered_stun_connect(void *sock, nr_transport_addr *addr);
+static int nr_socket_buffered_stun_write(void *obj,const void *msg, size_t len, size_t *written);
+static void nr_socket_buffered_stun_writable_cb(NR_SOCKET s, int how, void *arg);
+static int nr_socket_buffered_stun_listen(void *obj, int backlog);
+static int nr_socket_buffered_stun_accept(void *obj, nr_transport_addr *addrp, nr_socket **sockp);
+
+static nr_socket_vtbl nr_socket_buffered_stun_vtbl={
+ 2,
+ nr_socket_buffered_stun_destroy,
+ nr_socket_buffered_stun_sendto,
+ nr_socket_buffered_stun_recvfrom,
+ nr_socket_buffered_stun_getfd,
+ nr_socket_buffered_stun_getaddr,
+ nr_socket_buffered_stun_connect,
+ 0,
+ 0,
+ nr_socket_buffered_stun_close,
+ nr_socket_buffered_stun_listen,
+ nr_socket_buffered_stun_accept
+};
+
+void nr_socket_buffered_stun_set_readable_cb(nr_socket *sock,
+ NR_async_cb readable_cb, void *readable_cb_arg)
+{
+ nr_socket_buffered_stun *buf_sock = (nr_socket_buffered_stun *)sock->obj;
+
+ buf_sock->readable_cb = readable_cb;
+ buf_sock->readable_cb_arg = readable_cb_arg;
+}
+
+int nr_socket_buffered_set_connected_to(nr_socket *sock, nr_transport_addr *remote_addr)
+{
+ nr_socket_buffered_stun *buf_sock = (nr_socket_buffered_stun *)sock->obj;
+ int r, _status;
+
+ if ((r=nr_transport_addr_copy(&buf_sock->remote_addr, remote_addr)))
+ ABORT(r);
+
+ buf_sock->connected = 1;
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_socket_buffered_stun_create(nr_socket *inner, int max_pending,
+ nr_framing_type framing_type, nr_socket **sockp)
+{
+ int r, _status;
+ nr_socket_buffered_stun *sock = 0;
+ size_t frame_size;
+
+ if (!(sock = RCALLOC(sizeof(nr_socket_buffered_stun))))
+ ABORT(R_NO_MEMORY);
+
+ sock->inner = inner;
+ sock->framing_type = framing_type;
+
+ if ((r=nr_ip4_port_to_transport_addr(INADDR_ANY, 0, IPPROTO_UDP, &sock->remote_addr)))
+ ABORT(r);
+
+ switch (framing_type) {
+ case ICE_TCP_FRAMING:
+ frame_size = sizeof(nr_frame_header);
+ sock->buffer_size = sizeof(nr_frame_header) + NR_MAX_FRAME_SIZE;
+ sock->bytes_needed = sizeof(nr_frame_header);
+ break;
+ case TURN_TCP_FRAMING:
+ frame_size = 0;
+ sock->buffer_size = NR_STUN_MAX_MESSAGE_SIZE;
+ sock->bytes_needed = sizeof(nr_stun_message_header);
+ break;
+ default:
+ assert(0);
+ ABORT(R_BAD_ARGS);
+ }
+
+ /* TODO(ekr@rtfm.com): Check this */
+ if (!(sock->buffer = RMALLOC(sock->buffer_size)))
+ ABORT(R_NO_MEMORY);
+
+ sock->read_state = NR_ICE_SOCKET_READ_NONE;
+ sock->connected = 0;
+
+ STAILQ_INIT(&sock->pending_writes);
+ if ((r=nr_p_buf_ctx_create(sock->buffer_size, &sock->p_bufs)))
+ ABORT(r);
+ sock->max_pending = max_pending + frame_size;
+
+ if ((r=nr_socket_create_int(sock, &nr_socket_buffered_stun_vtbl, sockp)))
+ ABORT(r);
+
+ _status=0;
+abort:
+ if (_status && sock) {
+ void *sock_v = sock;
+ sock->inner = 0; /* Give up ownership so we don't destroy */
+ nr_socket_buffered_stun_destroy(&sock_v);
+ }
+ return(_status);
+}
+
+/* Note: This destroys the inner socket */
+int nr_socket_buffered_stun_destroy(void **objp)
+{
+ nr_socket_buffered_stun *sock;
+ NR_SOCKET fd;
+
+ if (!objp || !*objp)
+ return 0;
+
+ sock = (nr_socket_buffered_stun *)*objp;
+ *objp = 0;
+
+ /* Free the buffer if needed */
+ RFREE(sock->buffer);
+
+ /* Cancel waiting on the socket */
+ if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+ }
+
+ nr_p_buf_free_chain(sock->p_bufs, &sock->pending_writes);
+ nr_p_buf_ctx_destroy(&sock->p_bufs);
+ nr_socket_destroy(&sock->inner);
+ RFREE(sock);
+
+ return 0;
+}
+
+static int nr_socket_buffered_stun_sendto(void *obj,const void *msg, size_t len,
+ int flags, nr_transport_addr *to)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+ int r, _status;
+ size_t written;
+ nr_frame_header *frame = NULL;
+
+ /* Check that we are writing to the connected address if
+ connected */
+ if (!nr_transport_addr_is_wildcard(&sock->remote_addr)) {
+ if (nr_transport_addr_cmp(&sock->remote_addr, to, NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ r_log(LOG_GENERIC, LOG_ERR, "Sendto on connected socket doesn't match");
+ ABORT(R_BAD_DATA);
+ }
+ }
+
+ if (sock->framing_type == ICE_TCP_FRAMING) {
+
+ assert(len <= NR_MAX_FRAME_SIZE);
+ if (len > NR_MAX_FRAME_SIZE)
+ ABORT(R_FAILED);
+
+ if (!(frame = RMALLOC(len + sizeof(nr_frame_header))))
+ ABORT(R_NO_MEMORY);
+
+ frame->frame_length = htons(len);
+ memcpy(frame->data, msg, len);
+ len += sizeof(nr_frame_header);
+ msg = frame;
+ }
+
+ if ((r=nr_socket_buffered_stun_write(obj, msg, len, &written)))
+ ABORT(r);
+
+ if (len != written)
+ ABORT(R_IO_ERROR);
+
+ _status=0;
+abort:
+ RFREE(frame);
+ return _status;
+}
+
+static void nr_socket_buffered_stun_failed(nr_socket_buffered_stun *sock)
+ {
+ NR_SOCKET fd;
+
+ sock->read_state = NR_ICE_SOCKET_READ_FAILED;
+
+ /* Cancel waiting on the socket */
+ if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
+ }
+ }
+
+static int nr_socket_buffered_stun_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *from)
+{
+ int r, _status;
+ size_t bytes_read;
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+ nr_frame_header *frame = (nr_frame_header *)sock->buffer;
+ size_t skip_hdr_size = (sock->framing_type == ICE_TCP_FRAMING) ? sizeof(nr_frame_header) : 0;
+
+ if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
+ ABORT(R_FAILED);
+ }
+
+ while (sock->bytes_needed) {
+ /* Read all the expected bytes */
+ assert(sock->bytes_needed <= sock->buffer_size - sock->bytes_read);
+
+ if(r=nr_socket_read(sock->inner,
+ sock->buffer + sock->bytes_read,
+ sock->bytes_needed, &bytes_read, 0))
+ ABORT(r);
+
+ assert(bytes_read <= sock->bytes_needed);
+ sock->bytes_needed -= bytes_read;
+ sock->bytes_read += bytes_read;
+
+ /* Unfinished */
+ if (sock->bytes_needed)
+ ABORT(R_WOULDBLOCK);
+
+ /* No more bytes expected */
+ if (sock->read_state == NR_ICE_SOCKET_READ_NONE) {
+ size_t remaining_length;
+ if (sock->framing_type == ICE_TCP_FRAMING) {
+ if (sock->bytes_read < sizeof(nr_frame_header))
+ ABORT(R_BAD_DATA);
+ remaining_length = ntohs(frame->frame_length);
+ } else {
+ int tmp_length;
+
+ /* Parse the header */
+ if (r = nr_stun_message_length(sock->buffer, sock->bytes_read, &tmp_length))
+ ABORT(r);
+ assert(tmp_length >= 0);
+ if (tmp_length < 0)
+ ABORT(R_BAD_DATA);
+ remaining_length = tmp_length;
+
+ }
+ /* Check to see if we have enough room */
+ if ((sock->buffer_size - sock->bytes_read) < remaining_length)
+ ABORT(R_BAD_DATA);
+
+ sock->read_state = NR_ICE_SOCKET_READ_HDR;
+ /* Set ourselves up to read the rest of the data */
+ sock->bytes_needed = remaining_length;
+ }
+ }
+
+ assert(skip_hdr_size <= sock->bytes_read);
+ if (skip_hdr_size > sock->bytes_read)
+ ABORT(R_BAD_DATA);
+ sock->bytes_read -= skip_hdr_size;
+
+ if (maxlen < sock->bytes_read)
+ ABORT(R_BAD_ARGS);
+
+ *len = sock->bytes_read;
+ memcpy(buf, sock->buffer + skip_hdr_size, sock->bytes_read);
+
+ sock->bytes_read = 0;
+ sock->read_state = NR_ICE_SOCKET_READ_NONE;
+ sock->bytes_needed = (sock->framing_type == ICE_TCP_FRAMING) ? sizeof(nr_frame_header) : sizeof(nr_stun_message_header);
+
+ assert(!nr_transport_addr_is_wildcard(&sock->remote_addr));
+ if (!nr_transport_addr_is_wildcard(&sock->remote_addr)) {
+ if ((r=nr_transport_addr_copy(from, &sock->remote_addr)))
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ if (_status && (_status != R_WOULDBLOCK)) {
+ nr_socket_buffered_stun_failed(sock);
+ }
+
+ return(_status);
+}
+
+static int nr_socket_buffered_stun_getfd(void *obj, NR_SOCKET *fd)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+
+ return nr_socket_getfd(sock->inner, fd);
+}
+
+static int nr_socket_buffered_stun_getaddr(void *obj, nr_transport_addr *addrp)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+
+ return nr_socket_getaddr(sock->inner, addrp);
+}
+
+static int nr_socket_buffered_stun_close(void *obj)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+ NR_SOCKET fd;
+
+ /* Cancel waiting on the socket */
+ if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+ }
+
+ return nr_socket_close(sock->inner);
+}
+
+static int nr_socket_buffered_stun_listen(void *obj, int backlog)
+{
+ int r, _status;
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+
+ if (!sock->inner)
+ ABORT(R_FAILED);
+
+ if ((r=nr_socket_listen(sock->inner, backlog)))
+ ABORT(r);
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+
+static int nr_socket_buffered_stun_accept(void *obj, nr_transport_addr *addrp, nr_socket **sockp)
+{
+ nr_socket_buffered_stun *bsock = (nr_socket_buffered_stun *)obj;
+
+ return nr_socket_accept(bsock->inner, addrp, sockp);
+}
+
+static void nr_socket_buffered_stun_connected_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
+ int r, _status;
+ NR_SOCKET fd;
+
+ assert(!sock->connected);
+
+ sock->connected = 1;
+
+ if ((r=nr_socket_getfd(sock->inner, &fd)))
+ ABORT(r);
+ NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+
+ // once connected arm for read
+ if (sock->readable_cb) {
+ NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, sock->readable_cb, sock->readable_cb_arg);
+ }
+
+ if (sock->pending) {
+ r_log(LOG_GENERIC, LOG_INFO, "Invoking writable_cb on connected (%u)", (uint32_t) sock->pending);
+ nr_socket_buffered_stun_writable_cb(s, how, arg);
+ }
+
+ _status=0;
+abort:
+ if (_status) {
+ r_log(LOG_GENERIC, LOG_ERR, "Failure in nr_socket_buffered_stun_connected_cb: %d", _status);
+
+ }
+}
+
+static int nr_socket_buffered_stun_connect(void *obj, nr_transport_addr *addr)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+ int r, _status;
+
+ if ((r=nr_transport_addr_copy(&sock->remote_addr, addr)))
+ ABORT(r);
+
+ if ((r=nr_socket_connect(sock->inner, addr))) {
+ if (r == R_WOULDBLOCK) {
+ NR_SOCKET fd;
+
+ if ((r=nr_socket_getfd(sock->inner, &fd)))
+ ABORT(r);
+
+ NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE, nr_socket_buffered_stun_connected_cb, sock);
+ ABORT(R_WOULDBLOCK);
+ }
+ ABORT(r);
+ } else {
+ r_log(LOG_GENERIC, LOG_INFO, "Connected without blocking");
+ sock->connected = 1;
+ }
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_socket_buffered_stun_arm_writable_cb(nr_socket_buffered_stun *sock)
+{
+ int r, _status;
+ NR_SOCKET fd;
+
+ if ((r=nr_socket_getfd(sock->inner, &fd)))
+ ABORT(r);
+
+ NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE, nr_socket_buffered_stun_writable_cb, sock);
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_socket_buffered_stun_write(void *obj,const void *msg, size_t len, size_t *written)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
+ int already_armed = 0;
+ int r,_status;
+ size_t written2 = 0;
+ size_t original_len = len;
+
+ /* Buffers are close to full, report error. Do this now so we never
+ get partial writes */
+ if ((sock->pending + len) > sock->max_pending) {
+ r_log(LOG_GENERIC, LOG_INFO, "Write buffer for %s full (%u + %u > %u) - re-arming @%p",
+ sock->remote_addr.as_string, (uint32_t)sock->pending, (uint32_t)len, (uint32_t)sock->max_pending,
+ &(sock->pending));
+ ABORT(R_WOULDBLOCK);
+ }
+
+
+ if (sock->connected && !sock->pending) {
+ r = nr_socket_write(sock->inner, msg, len, &written2, 0);
+ if (r) {
+ if (r != R_WOULDBLOCK) {
+ r_log(LOG_GENERIC, LOG_ERR, "Write error for %s - %d",
+ sock->remote_addr.as_string, r);
+ ABORT(r);
+ }
+ r_log(LOG_GENERIC, LOG_INFO, "Write of %" PRIu64 " blocked for %s",
+ (uint64_t) len, sock->remote_addr.as_string);
+
+ written2=0;
+ }
+ } else {
+ already_armed = 1;
+ }
+
+ /* Buffer what's left */
+ len -= written2;
+
+ if (len) {
+ if ((r=nr_p_buf_write_to_chain(sock->p_bufs, &sock->pending_writes,
+ ((UCHAR *)msg) + written2, len))) {
+ r_log(LOG_GENERIC, LOG_ERR, "Write_to_chain error for %s - %d",
+ sock->remote_addr.as_string, r);
+
+ ABORT(r);
+ }
+
+ sock->pending += len;
+ }
+
+ if (sock->pending) {
+ if (!already_armed) {
+ if ((r=nr_socket_buffered_stun_arm_writable_cb(sock)))
+ ABORT(r);
+ }
+ r_log(LOG_GENERIC, LOG_INFO, "Write buffer not empty for %s %u - %s armed (@%p),%s connected",
+ sock->remote_addr.as_string, (uint32_t)sock->pending,
+ already_armed ? "already" : "", &sock->pending,
+ sock->connected ? "" : " not");
+ }
+
+ *written = original_len;
+
+ _status=0;
+abort:
+ return _status;
+}
+
+static void nr_socket_buffered_stun_writable_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
+ int r,_status;
+ nr_p_buf *n1, *n2;
+
+ if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
+ ABORT(R_FAILED);
+ }
+
+ /* Try to flush */
+ STAILQ_FOREACH_SAFE(n1, &sock->pending_writes, entry, n2) {
+ size_t written = 0;
+
+ if ((r=nr_socket_write(sock->inner, n1->data + n1->r_offset,
+ n1->length - n1->r_offset,
+ &written, 0))) {
+
+ r_log(LOG_GENERIC, LOG_ERR, "Write error for %s - %d",
+ sock->remote_addr.as_string, r);
+ ABORT(r);
+ }
+
+ n1->r_offset += written;
+ assert(sock->pending >= written);
+ sock->pending -= written;
+
+ if (n1->r_offset < n1->length) {
+ /* We wrote something, but not everything */
+ r_log(LOG_GENERIC, LOG_INFO, "Write in callback didn't write all (remaining %u of %u) for %s",
+ n1->length - n1->r_offset, n1->length,
+ sock->remote_addr.as_string);
+ ABORT(R_WOULDBLOCK);
+ }
+
+ /* We are done with this p_buf */
+ STAILQ_REMOVE_HEAD(&sock->pending_writes, entry);
+ nr_p_buf_free(sock->p_bufs, n1);
+ }
+
+ assert(!sock->pending);
+ _status=0;
+abort:
+ r_log(LOG_GENERIC, LOG_INFO, "Writable_cb %s (%u (%p) pending)",
+ sock->remote_addr.as_string, (uint32_t)sock->pending, &(sock->pending));
+ if (_status && _status != R_WOULDBLOCK) {
+ r_log(LOG_GENERIC, LOG_ERR, "Failure in writable_cb: %d", _status);
+ nr_socket_buffered_stun_failed(sock);
+ } else if (sock->pending) {
+ nr_socket_buffered_stun_arm_writable_cb(sock);
+ }
+}
diff --git a/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.h b/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.h
new file mode 100644
index 000000000..fa65e4b08
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.h
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _nr_socket_buffered_stun_h
+#define _nr_socket_buffered_stun_h
+
+#include "nr_socket.h"
+
+/* Wrapper socket which provides buffered STUN-oriented I/O
+
+ 1. Writes don't block and are automatically flushed when needed.
+ 2. All reads are in units of STUN messages
+
+ This socket takes ownership of the inner socket |sock|.
+ */
+
+typedef enum {
+ TURN_TCP_FRAMING=0,
+ ICE_TCP_FRAMING
+} nr_framing_type;
+
+void nr_socket_buffered_stun_set_readable_cb(nr_socket *sock,
+ NR_async_cb readable_cb, void *readable_cb_arg);
+
+int nr_socket_buffered_stun_create(nr_socket *inner, int max_pending,
+ nr_framing_type framing_type, nr_socket **sockp);
+
+int nr_socket_buffered_set_connected_to(nr_socket *sock,
+ nr_transport_addr *remote_addr);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.c b/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.c
new file mode 100644
index 000000000..a12966625
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.c
@@ -0,0 +1,198 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: nr_socket_turn.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#ifdef USE_TURN
+
+#include <csi_platform.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include "stun.h"
+#include "turn_client_ctx.h"
+#include "nr_socket_turn.h"
+
+
+static char *nr_socket_turn_magic_cookie = "nr_socket_turn";
+
+typedef struct nr_socket_turn_ {
+ char *magic_cookie;
+ nr_turn_client_ctx *turn;
+} nr_socket_turn;
+
+
+static int nr_socket_turn_destroy(void **objp);
+static int nr_socket_turn_sendto(void *obj,const void *msg, size_t len,
+ int flags, nr_transport_addr *to);
+static int nr_socket_turn_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *from);
+static int nr_socket_turn_getfd(void *obj, NR_SOCKET *fd);
+static int nr_socket_turn_getaddr(void *obj, nr_transport_addr *addrp);
+static int nr_socket_turn_close(void *obj);
+
+static nr_socket_vtbl nr_socket_turn_vtbl={
+ 2,
+ nr_socket_turn_destroy,
+ nr_socket_turn_sendto,
+ nr_socket_turn_recvfrom,
+ nr_socket_turn_getfd,
+ nr_socket_turn_getaddr,
+ 0,
+ 0,
+ 0,
+ nr_socket_turn_close,
+ 0,
+ 0
+};
+
+int nr_socket_turn_create(nr_socket *sock, nr_socket **sockp)
+ {
+ int r,_status;
+ nr_socket_turn *sturn=0;
+
+ if(!(sturn=RCALLOC(sizeof(nr_socket_turn))))
+ ABORT(R_NO_MEMORY);
+
+ sturn->magic_cookie = nr_socket_turn_magic_cookie;
+
+ if(r=nr_socket_create_int(sturn, &nr_socket_turn_vtbl, sockp))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_socket_turn_destroy((void **)&sturn);
+ }
+ return(_status);
+ }
+
+static int nr_socket_turn_destroy(void **objp)
+ {
+ int _status;
+ nr_socket_turn *sturn;
+
+ if(!objp || !*objp)
+ return(0);
+
+ sturn=*objp;
+ *objp=0;
+
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+
+ /* we don't own the socket, so don't destroy it */
+
+ RFREE(sturn);
+
+ _status=0;
+ return(_status);
+ }
+
+static int nr_socket_turn_sendto(void *obj,const void *msg, size_t len,
+ int flags, nr_transport_addr *addr)
+ {
+ int r,_status;
+ nr_socket_turn *sturn=obj;
+
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+ assert(sturn->turn);
+
+ if ((r = nr_turn_client_send_indication(sturn->turn, msg, len, flags,
+ addr)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_socket_turn_recvfrom(void *obj,void * restrict buf,
+ size_t maxlen, size_t *len, int flags, nr_transport_addr *addr)
+ {
+ /* Reading from TURN sockets is done by the indication
+ processing code in turn_client_ctx. */
+ assert(0);
+
+ return(R_INTERNAL);
+ }
+
+static int nr_socket_turn_getfd(void *obj, NR_SOCKET *fd)
+ {
+ /* You should never directly be touching this fd. */
+ assert(0);
+
+ return(R_INTERNAL);
+ }
+
+static int nr_socket_turn_getaddr(void *obj, nr_transport_addr *addrp)
+ {
+ nr_socket_turn *sturn=obj;
+ int r, _status;
+
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+ assert(sturn->turn);
+
+ /* This returns the relayed address */
+ if ((r=nr_turn_client_get_relayed_address(sturn->turn, addrp)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_socket_turn_close(void *obj)
+ {
+ /* No-op */
+#ifndef NDEBUG
+ nr_socket_turn *sturn=obj;
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+#endif
+
+ return 0;
+ }
+
+int nr_socket_turn_set_ctx(nr_socket *sock, nr_turn_client_ctx *ctx)
+{
+ nr_socket_turn *sturn=(nr_socket_turn*)sock->obj;
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
+ assert(!sturn->turn);
+
+ sturn->turn = ctx;
+
+ return 0;
+}
+
+#endif /* USE_TURN */
diff --git a/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.h b/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.h
new file mode 100644
index 000000000..c9d36d333
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/nr_socket_turn.h
@@ -0,0 +1,48 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _nr_socket_turn_h
+#define _nr_socket_turn_h
+
+#include "nr_socket.h"
+
+/* This is a partial implementation of an nr_socket wrapped
+ around TURN. It implements only the nr_socket features
+ actually used by the ICE stack. You can't, for instance,
+ read off the socket */
+int nr_socket_turn_create(nr_socket *sock, nr_socket **sockp);
+int nr_socket_turn_set_ctx(nr_socket *sock, nr_turn_client_ctx *ctx);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun.h b/media/mtransport/third_party/nICEr/src/stun/stun.h
new file mode 100644
index 000000000..8e5a60750
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun.h
@@ -0,0 +1,216 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _STUN_H
+#define _STUN_H
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifndef LINUX
+#include <net/if.h>
+#if !defined(__OpenBSD__) && !defined(__NetBSD__)
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#else
+#include <linux/if.h>
+#endif
+#ifndef BSD
+#include <net/route.h>
+#endif
+#include <netinet/in.h>
+#ifndef LINUX
+#include <netinet/in_var.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+#include <time.h>
+
+#include "nr_api.h"
+#include "stun_msg.h"
+#include "stun_build.h"
+#include "stun_codec.h"
+#include "stun_hint.h"
+#include "stun_util.h"
+#include "nr_socket.h"
+#include "stun_client_ctx.h"
+#include "stun_server_ctx.h"
+#include "stun_proc.h"
+
+#define NR_STUN_VERSION "rfc3489bis-11"
+#define NR_STUN_PORT 3478
+
+/* STUN attributes */
+#define NR_STUN_ATTR_MAPPED_ADDRESS 0x0001
+#define NR_STUN_ATTR_USERNAME 0x0006
+#define NR_STUN_ATTR_MESSAGE_INTEGRITY 0x0008
+#define NR_STUN_ATTR_ERROR_CODE 0x0009
+#define NR_STUN_ATTR_UNKNOWN_ATTRIBUTES 0x000A
+#define NR_STUN_ATTR_REALM 0x0014
+#define NR_STUN_ATTR_NONCE 0x0015
+#define NR_STUN_ATTR_XOR_MAPPED_ADDRESS 0x0020
+#define NR_STUN_ATTR_SERVER 0x8022
+#define NR_STUN_ATTR_ALTERNATE_SERVER 0x8023
+#define NR_STUN_ATTR_FINGERPRINT 0x8028
+
+/* for backwards compatibility with obsolete versions of the STUN spec */
+#define NR_STUN_ATTR_OLD_XOR_MAPPED_ADDRESS 0x8020
+
+#ifdef USE_STUND_0_96
+#define NR_STUN_ATTR_OLD_CHANGE_REQUEST 0x0003
+#endif /* USE_STUND_0_96 */
+
+#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+/* for backwards compatibility with obsolete versions of the STUN spec */
+#define NR_STUN_ATTR_OLD_PASSWORD 0x0007
+#define NR_STUN_ATTR_OLD_RESPONSE_ADDRESS 0x0002
+#define NR_STUN_ATTR_OLD_SOURCE_ADDRESS 0x0004
+#define NR_STUN_ATTR_OLD_CHANGED_ADDRESS 0x0005
+#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
+
+#ifdef USE_ICE
+/* ICE attributes */
+#define NR_STUN_ATTR_PRIORITY 0x0024
+#define NR_STUN_ATTR_USE_CANDIDATE 0x0025
+#define NR_STUN_ATTR_ICE_CONTROLLED 0x8029
+#define NR_STUN_ATTR_ICE_CONTROLLING 0x802A
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+/* TURN attributes */
+#define NR_STUN_ATTR_LIFETIME 0x000d
+#define NR_STUN_ATTR_XOR_PEER_ADDRESS 0x0012
+#define NR_STUN_ATTR_DATA 0x0013
+#define NR_STUN_ATTR_XOR_RELAY_ADDRESS 0x0016
+#define NR_STUN_ATTR_REQUESTED_TRANSPORT 0x0019
+
+#define NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP 17
+#endif /* USE_TURN */
+
+/*
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |M|M|M|M|M|C|M|M|M|C|M|M|M|M|
+ * |1|1|9|8|7|1|6|5|4|0|3|2|1|0|
+ * |1|0| | | | | | | | | | | | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Figure 3: Format of STUN Message Type Field
+ */
+#define NR_STUN_METHOD_TYPE_BITS(m) \
+ ((((m) & 0xf80) << 2) | (((m) & 0x070) << 1) | ((m) & 0x00f))
+
+#define NR_STUN_CLASS_TYPE_BITS(c) \
+ ((((c) & 0x002) << 7) | (((c) & 0x001) << 4))
+
+#define NR_STUN_GET_TYPE_METHOD(t) \
+ ((((t) >> 2) & 0xf80) | (((t) >> 1) & 0x070) | ((t) & 0x00f))
+
+#define NR_STUN_GET_TYPE_CLASS(t) \
+ ((((t) >> 7) & 0x002) | (((t) >> 4) & 0x001))
+
+#define NR_STUN_TYPE(m,c) (NR_STUN_METHOD_TYPE_BITS((m)) | NR_STUN_CLASS_TYPE_BITS((c)))
+
+/* building blocks for message types */
+#define NR_METHOD_BINDING 0x001
+#define NR_CLASS_REQUEST 0x0
+#define NR_CLASS_INDICATION 0x1
+#define NR_CLASS_RESPONSE 0x2
+#define NR_CLASS_ERROR_RESPONSE 0x3
+
+/* define types for STUN messages */
+#define NR_STUN_MSG_BINDING_REQUEST NR_STUN_TYPE(NR_METHOD_BINDING, \
+ NR_CLASS_REQUEST)
+#define NR_STUN_MSG_BINDING_INDICATION NR_STUN_TYPE(NR_METHOD_BINDING, \
+ NR_CLASS_INDICATION)
+#define NR_STUN_MSG_BINDING_RESPONSE NR_STUN_TYPE(NR_METHOD_BINDING, \
+ NR_CLASS_RESPONSE)
+#define NR_STUN_MSG_BINDING_ERROR_RESPONSE NR_STUN_TYPE(NR_METHOD_BINDING, \
+ NR_CLASS_ERROR_RESPONSE)
+
+#ifdef USE_TURN
+/* building blocks for TURN message types */
+#define NR_METHOD_ALLOCATE 0x003
+#define NR_METHOD_REFRESH 0x004
+
+#define NR_METHOD_SEND 0x006
+#define NR_METHOD_DATA 0x007
+#define NR_METHOD_CREATE_PERMISSION 0x008
+#define NR_METHOD_CHANNEL_BIND 0x009
+
+/* define types for a TURN message */
+#define NR_STUN_MSG_ALLOCATE_REQUEST NR_STUN_TYPE(NR_METHOD_ALLOCATE, \
+ NR_CLASS_REQUEST)
+#define NR_STUN_MSG_ALLOCATE_RESPONSE NR_STUN_TYPE(NR_METHOD_ALLOCATE, \
+ NR_CLASS_RESPONSE)
+#define NR_STUN_MSG_ALLOCATE_ERROR_RESPONSE NR_STUN_TYPE(NR_METHOD_ALLOCATE, \
+ NR_CLASS_ERROR_RESPONSE)
+#define NR_STUN_MSG_REFRESH_REQUEST NR_STUN_TYPE(NR_METHOD_REFRESH, \
+ NR_CLASS_REQUEST)
+#define NR_STUN_MSG_REFRESH_RESPONSE NR_STUN_TYPE(NR_METHOD_REFRESH, \
+ NR_CLASS_RESPONSE)
+#define NR_STUN_MSG_REFRESH_ERROR_RESPONSE NR_STUN_TYPE(NR_METHOD_REFRESH, \
+ NR_CLASS_ERROR_RESPONSE)
+
+#define NR_STUN_MSG_SEND_INDICATION NR_STUN_TYPE(NR_METHOD_SEND, \
+ NR_CLASS_INDICATION)
+#define NR_STUN_MSG_DATA_INDICATION NR_STUN_TYPE(NR_METHOD_DATA, \
+ NR_CLASS_INDICATION)
+
+#define NR_STUN_MSG_PERMISSION_REQUEST NR_STUN_TYPE(NR_METHOD_CREATE_PERMISSION, \
+ NR_CLASS_REQUEST)
+#define NR_STUN_MSG_PERMISSION_RESPONSE NR_STUN_TYPE(NR_METHOD_CREATE_PERMISSION, \
+ NR_CLASS_RESPONSE)
+#define NR_STUN_MSG_PERMISSION_ERROR_RESPONSE NR_STUN_TYPE(NR_METHOD_CREATE_PERMISSION, \
+ NR_CLASS_ERROR_RESPONSE)
+
+#define NR_STUN_MSG_CHANNEL_BIND_REQUEST NR_STUN_TYPE(NR_METHOD_CHANNEL_BIND, \
+ NR_CLASS_REQUEST)
+#define NR_STUN_MSG_CHANNEL_BIND_RESPONSE NR_STUN_TYPE(NR_METHOD_CHANNEL_BIND, \
+ NR_CLASS_RESPONSE)
+#define NR_STUN_MSG_CHANNEL_BIND_ERROR_RESPONSE NR_STUN_TYPE(NR_METHOD_CHANNEL_BIND, \
+ NR_CLASS_ERROR_RESPONSE)
+
+
+#endif /* USE_TURN */
+
+
+#define NR_STUN_AUTH_RULE_OPTIONAL (1<<0)
+#define NR_STUN_AUTH_RULE_SHORT_TERM (1<<8)
+#define NR_STUN_AUTH_RULE_LONG_TERM (1<<9)
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_build.c b/media/mtransport/third_party/nICEr/src/stun/stun_build.c
new file mode 100644
index 000000000..b029501a7
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_build.c
@@ -0,0 +1,614 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_build.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <csi_platform.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "nr_api.h"
+#include "stun.h"
+#include "registry.h"
+#include "stun_reg.h"
+#include "nr_crypto.h"
+
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.1 */
+/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.1 */
+/* note that S 10.1.1 states the message MUST include MESSAGE-INTEGRITY
+ * and USERNAME, but that's not correct -- for instance ICE keepalive
+ * messages don't include these (See draft-ietf-mmusic-ice-18.txt S 10:
+ * "If STUN is being used for keepalives, a STUN Binding Indication is
+ * used. The Indication MUST NOT utilize any authentication mechanism")
+ */
+int
+nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ assert(NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_REQUEST
+ || NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_INDICATION);
+
+ *msg = 0;
+
+ if ((r=nr_stun_message_create(&req)))
+ ABORT(r);
+
+ req->header.type = msg_type;
+
+ nr_crypto_random_bytes((UCHAR*)&req->header.id,sizeof(req->header.id));
+
+ switch (mode) {
+ default:
+ if ((r=nr_stun_message_add_fingerprint_attribute(req)))
+ ABORT(r);
+ /* fall through */
+ case NR_STUN_MODE_STUN_NO_AUTH:
+ req->header.magic_cookie = NR_STUN_MAGIC_COOKIE;
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MODE_STUND_0_96:
+ req->header.magic_cookie = NR_STUN_MAGIC_COOKIE2;
+
+ /* actually, stund 0.96 just ignores the fingerprint
+ * attribute, but don't bother to send it */
+
+ break;
+#endif /* USE_STUND_0_96 */
+
+ }
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) RFREE(req);
+ return _status;
+}
+
+int
+nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_username_attribute(req, params->username)))
+ ABORT(r);
+
+ if (params->realm && params->nonce) {
+ if ((r=nr_stun_message_add_realm_attribute(req, params->realm)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_nonce_attribute(req, params->nonce)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
+ ABORT(r);
+ }
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+int
+nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_username_attribute(req, params->username)))
+ ABORT(r);
+
+ if (params->password) {
+ if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
+ ABORT(r);
+ }
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+int
+nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN_NO_AUTH, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+int
+nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *ind = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_INDICATION, &ind)))
+ ABORT(r);
+
+ *msg = ind;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&ind);
+ return _status;
+}
+
+#ifdef USE_STUND_0_96
+int
+nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUND_0_96, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_change_request_attribute(req, 0)))
+ ABORT(r);
+
+ assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0));
+ assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0));
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+#endif /* USE_STUND_0_96 */
+
+#ifdef USE_ICE
+int
+nr_stun_build_use_candidate(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_username_attribute(req, params->username)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_message_integrity_attribute(req, &params->password)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_use_candidate_attribute(req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
+ ABORT(r);
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+int
+nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_username_attribute(req, params->username)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_message_integrity_attribute(req, &params->password)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
+ ABORT(r);
+
+ switch (params->control) {
+ case NR_ICE_CONTROLLING:
+ if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
+ ABORT(r);
+ break;
+ case NR_ICE_CONTROLLED:
+ if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker)))
+ ABORT(r);
+ break;
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ }
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+
+#ifndef __isascii
+#define __isascii(c) (((c) & ~0x7F) == 0)
+#endif
+
+/* Long-term passwords are computed over the key:
+
+ key = MD5(username ":" realm ":" SASLprep(password))
+
+ Per RFC 5389 S 15.4
+*/
+int
+nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm,
+ Data *password, Data *hmac_key)
+{
+ char digest_input[1000];
+ int i;
+ int r, _status;
+ size_t len;
+
+ /* First check that the password is ASCII. We are supposed to
+ SASLprep but we don't support this yet
+ TODO(ekr@rtfm.com): Add SASLprep for password.
+ */
+ for (i=0; i<password->len; i++) {
+ if (!__isascii(password->data[i]))
+ ABORT(R_BAD_DATA);
+ }
+
+ if (hmac_key->len < 16)
+ ABORT(R_BAD_ARGS);
+
+ snprintf(digest_input, sizeof(digest_input), "%s:%s:", username, realm);
+ if ((sizeof(digest_input) - strlen(digest_input)) < password->len)
+ ABORT(R_BAD_DATA);
+
+ len = strlen(digest_input);
+ memcpy(digest_input + len, password->data, password->len);
+
+
+ if (r=nr_crypto_md5((UCHAR *)digest_input, len + password->len, hmac_key->data))
+ ABORT(r);
+ hmac_key->len=16;
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int
+nr_stun_build_auth_params(nr_stun_client_auth_params *auth, nr_stun_message *req)
+{
+ int r, _status;
+ UCHAR hmac_key_d[16];
+ Data hmac_key;
+
+ ATTACH_DATA(hmac_key, hmac_key_d);
+
+ if (!auth->authenticate)
+ goto done;
+
+ assert(auth->username);
+ assert(auth->password.len);
+ assert(auth->realm);
+ assert(auth->nonce);
+
+ if (r=nr_stun_compute_lt_message_integrity_password(auth->username,
+ auth->realm,
+ &auth->password,
+ &hmac_key))
+ ABORT(r);
+
+ if (!auth->username) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no username provided");
+ ABORT(R_INTERNAL);
+ }
+
+ if (!auth->password.len) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no password provided");
+ ABORT(R_INTERNAL);
+ }
+
+ if (!auth->realm) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no realm provided");
+ ABORT(R_INTERNAL);
+ }
+
+ if (!auth->nonce) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no nonce provided");
+ ABORT(R_INTERNAL);
+ }
+
+ if ((r=nr_stun_message_add_username_attribute(req, auth->username)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_realm_attribute(req, auth->realm)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_nonce_attribute(req, auth->nonce)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_message_integrity_attribute(req, &hmac_key)))
+ ABORT(r);
+
+done:
+ _status=0;
+abort:
+ return(_status);
+}
+
+int
+nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_ALLOCATE_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_requested_transport_attribute(req, NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
+ ABORT(r);
+
+ /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
+
+ if ((r=nr_stun_build_auth_params(auth, req)))
+ ABORT(r);
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+
+int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_REFRESH_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
+ ABORT(r);
+
+
+ /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
+
+ if ((r=nr_stun_build_auth_params(auth, req)))
+ ABORT(r);
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+
+int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *req = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_PERMISSION_REQUEST, &req)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_xor_peer_address_attribute(req, &params->remote_addr)))
+ ABORT(r);
+
+ if ((r=nr_stun_build_auth_params(auth, req)))
+ ABORT(r);
+
+ *msg = req;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&req);
+ return _status;
+}
+
+int
+nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *ind = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_SEND_INDICATION, &ind)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, &params->remote_addr)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
+ ABORT(r);
+
+ *msg = ind;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&ind);
+ return _status;
+}
+
+int
+nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg)
+{
+ int r,_status;
+ nr_stun_message *ind = 0;
+
+ if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_DATA_INDICATION, &ind)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, &params->remote_addr)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
+ ABORT(r);
+
+ *msg = ind;
+
+ _status=0;
+ abort:
+ if (_status) nr_stun_message_destroy(&ind);
+ return _status;
+}
+
+#endif /* USE_TURN */
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
+int
+nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res)
+{
+ int r,_status;
+ int request_method;
+ char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
+
+ /* set up information for default response */
+
+ request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
+ res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_RESPONSE);
+ res->header.magic_cookie = req->header.magic_cookie;
+ memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Mapped Address = %s", from->as_string);
+
+ if ((r=nr_stun_message_add_xor_mapped_address_attribute(res, from)))
+ ABORT(r);
+
+ if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
+ if ((r=nr_stun_message_add_server_attribute(res, server_name)))
+ ABORT(r);
+ }
+
+ if (res->header.magic_cookie == NR_STUN_MAGIC_COOKIE) {
+ if (password != 0) {
+ if ((r=nr_stun_message_add_message_integrity_attribute(res, password)))
+ ABORT(r);
+ }
+
+ if ((r=nr_stun_message_add_fingerprint_attribute(res)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
+void
+nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg)
+{
+ char *str;
+ int request_method;
+ char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
+
+ if (number < 300 || number > 699)
+ number = 500;
+
+ r_log(NR_LOG_STUN, LOG_INFO, "Responding with error %d: %s", number, msg);
+
+ request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
+ res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_ERROR_RESPONSE);
+ res->header.magic_cookie = req->header.magic_cookie;
+ memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
+
+ /* during development we should never see 500s (hopefully not in deployment either) */
+
+ str = 0;
+ switch (number) {
+ case 300: str = "Try Alternate"; break;
+ case 400: str = "Bad Request"; break;
+ case 401: str = "Unauthorized"; break;
+ case 420: str = "Unknown Attribute"; break;
+ case 438: str = "Stale Nonce"; break;
+#ifdef USE_ICE
+ case 487: str = "Role Conflict"; break;
+#endif
+ case 500: str = "Server Error"; break;
+ }
+ if (str == 0) {
+ str = "Unknown";
+ }
+
+ if (nr_stun_message_add_error_code_attribute(res, number, str)) {
+ assert(0); /* should never happen */
+ }
+
+ if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
+ nr_stun_message_add_server_attribute(res, server_name);
+ }
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_build.h b/media/mtransport/third_party/nICEr/src/stun/stun_build.h
new file mode 100644
index 000000000..c3f91a87b
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_build.h
@@ -0,0 +1,147 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _stun_build_h
+#define _stun_build_h
+
+#include "stun.h"
+
+#define NR_STUN_MODE_STUN 1
+#ifdef USE_STUND_0_96
+#define NR_STUN_MODE_STUND_0_96 2 /* backwards compatibility mode */
+#endif /* USE_STUND_0_96 */
+#define NR_STUN_MODE_STUN_NO_AUTH 3
+int nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg);
+
+typedef struct nr_stun_client_stun_binding_request_params_ {
+ char *username;
+ Data *password;
+ char *nonce;
+ char *realm;
+} nr_stun_client_stun_binding_request_params;
+
+int nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg);
+int nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg);
+int nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg);
+
+
+typedef struct nr_stun_client_stun_keepalive_params_ {
+#if defined(WIN32) || defined(__clang__)
+ // VC++ and clang give error and warning respectively if no members
+ int dummy;
+#endif
+} nr_stun_client_stun_keepalive_params;
+
+int nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg);
+
+
+#ifdef USE_STUND_0_96
+typedef struct nr_stun_client_stun_binding_request_stund_0_96_params_ {
+#ifdef WIN32 // silly VC++ gives error if no members
+ int dummy;
+#endif
+} nr_stun_client_stun_binding_request_stund_0_96_params;
+
+int nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg);
+#endif /* USE_STUND_0_96 */
+
+
+#ifdef USE_ICE
+typedef struct nr_stun_client_ice_binding_request_params_ {
+ char *username;
+ Data password;
+ UINT4 priority;
+ int control;
+#define NR_ICE_CONTROLLING 1
+#define NR_ICE_CONTROLLED 2
+ UINT8 tiebreaker;
+} nr_stun_client_ice_binding_request_params;
+
+int nr_stun_build_use_candidate(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg);
+
+int nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg);
+#endif /* USE_ICE */
+
+
+typedef struct nr_stun_client_auth_params_ {
+ char authenticate;
+ char *username;
+ char *realm;
+ char *nonce;
+ Data password;
+} nr_stun_client_auth_params;
+
+#ifdef USE_TURN
+typedef struct nr_stun_client_allocate_request_params_ {
+ UINT4 lifetime_secs;
+} nr_stun_client_allocate_request_params;
+
+int nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg);
+
+
+typedef struct nr_stun_client_refresh_request_params_ {
+ UINT4 lifetime_secs;
+} nr_stun_client_refresh_request_params;
+
+int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg);
+
+
+
+typedef struct nr_stun_client_permission_request_params_ {
+ nr_transport_addr remote_addr;
+} nr_stun_client_permission_request_params;
+
+int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg);
+
+
+typedef struct nr_stun_client_send_indication_params_ {
+ nr_transport_addr remote_addr;
+ Data data;
+} nr_stun_client_send_indication_params;
+
+int nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg);
+
+typedef struct nr_stun_client_data_indication_params_ {
+ nr_transport_addr remote_addr;
+ Data data;
+} nr_stun_client_data_indication_params;
+
+int nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg);
+#endif /* USE_TURN */
+
+int nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res);
+void nr_stun_form_error_response(nr_stun_message *request, nr_stun_message* response, int number, char* msg);
+int nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm,
+ Data *password, Data *hmac_key);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.c b/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.c
new file mode 100644
index 000000000..e8d91982b
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.c
@@ -0,0 +1,824 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_client_ctx.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include <nr_api.h>
+#include "stun.h"
+#include "async_timer.h"
+#include "registry.h"
+#include "stun_reg.h"
+#include "nr_crypto.h"
+#include "r_time.h"
+
+static int nr_stun_client_send_request(nr_stun_client_ctx *ctx);
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg);
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password);
+
+#define NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD 1
+#define NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK 2
+
+int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
+ {
+ nr_stun_client_ctx *ctx=0;
+ char allow_loopback;
+ int r,_status;
+
+ if ((r=nr_stun_startup()))
+ ABORT(r);
+
+ if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ ctx->state=NR_STUN_CLIENT_STATE_INITTED;
+
+ if(!(ctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ ctx->sock=sock;
+
+ nr_socket_getaddr(sock,&ctx->my_addr);
+ nr_transport_addr_copy(&ctx->peer_addr,peer);
+
+ if (RTO != 0) {
+ ctx->rto_ms = RTO;
+ } else if (NR_reg_get_uint4(NR_STUN_REG_PREF_CLNT_RETRANSMIT_TIMEOUT, &ctx->rto_ms)) {
+ ctx->rto_ms = 100;
+ }
+
+ if (NR_reg_get_double(NR_STUN_REG_PREF_CLNT_RETRANSMIT_BACKOFF, &ctx->retransmission_backoff_factor))
+ ctx->retransmission_backoff_factor = 2.0;
+
+ if (NR_reg_get_uint4(NR_STUN_REG_PREF_CLNT_MAXIMUM_TRANSMITS, &ctx->maximum_transmits))
+ ctx->maximum_transmits = 7;
+
+ if (NR_reg_get_uint4(NR_STUN_REG_PREF_CLNT_FINAL_RETRANSMIT_BACKOFF, &ctx->maximum_transmits_timeout_ms))
+ ctx->maximum_transmits_timeout_ms = 16 * ctx->rto_ms;
+
+ ctx->mapped_addr_check_mask = NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD;
+ if (NR_reg_get_char(NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, &allow_loopback) ||
+ !allow_loopback) {
+ ctx->mapped_addr_check_mask |= NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK;
+ }
+
+ if (ctx->my_addr.protocol == IPPROTO_TCP) {
+ /* Because TCP is reliable there is only one final timeout value.
+ * We store the timeout value for TCP in here, because timeout_ms gets
+ * reset to 0 in client_reset() which gets called from client_start() */
+ ctx->maximum_transmits_timeout_ms = ctx->rto_ms *
+ pow(ctx->retransmission_backoff_factor,
+ ctx->maximum_transmits);
+ ctx->maximum_transmits = 1;
+ }
+
+ *ctxp=ctx;
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_stun_client_ctx_destroy(&ctx);
+ }
+ return(_status);
+ }
+
+static void nr_stun_client_fire_finished_cb(nr_stun_client_ctx *ctx)
+ {
+ if (ctx->finished_cb) {
+ NR_async_cb finished_cb = ctx->finished_cb;
+ ctx->finished_cb = 0; /* prevent 2nd call */
+ /* finished_cb call must be absolutely last thing in function
+ * because as a side effect this ctx may be operated on in the
+ * callback */
+ finished_cb(0,0,ctx->cb_arg);
+ }
+ }
+
+int nr_stun_client_start(nr_stun_client_ctx *ctx, int mode, NR_async_cb finished_cb, void *cb_arg)
+ {
+ int r,_status;
+
+ if (ctx->state != NR_STUN_CLIENT_STATE_INITTED)
+ ABORT(R_NOT_PERMITTED);
+
+ ctx->mode=mode;
+
+ ctx->state=NR_STUN_CLIENT_STATE_RUNNING;
+ ctx->finished_cb=finished_cb;
+ ctx->cb_arg=cb_arg;
+
+ if(mode!=NR_STUN_CLIENT_MODE_KEEPALIVE){
+ if(r=nr_stun_client_send_request(ctx))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) {
+ nr_stun_client_fire_finished_cb(ctx);
+ }
+
+ return(_status);
+ }
+
+int nr_stun_client_restart(nr_stun_client_ctx *ctx)
+ {
+ int r,_status;
+ int mode;
+ NR_async_cb finished_cb;
+ void *cb_arg;
+ nr_stun_message_attribute *ec;
+ nr_stun_message_attribute *as;
+
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
+ ABORT(R_NOT_PERMITTED);
+
+ assert(ctx->retry_ct <= 2);
+ if (ctx->retry_ct > 2)
+ ABORT(R_NOT_PERMITTED);
+
+ ++ctx->retry_ct;
+
+ mode = ctx->mode;
+ finished_cb = ctx->finished_cb;
+ cb_arg = ctx->cb_arg;
+
+ if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_ERROR_CODE, &ec)
+ && ec->u.error_code.number == 300) {
+ if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_ALTERNATE_SERVER, &as)) {
+ nr_transport_addr_copy(&ctx->peer_addr, &as->u.alternate_server);
+ }
+ }
+
+ nr_stun_client_reset(ctx);
+
+ if (r=nr_stun_client_start(ctx, mode, finished_cb, cb_arg))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int
+nr_stun_client_reset(nr_stun_client_ctx *ctx)
+{
+ /* Cancel the timer firing */
+ if (ctx->timer_handle){
+ NR_async_timer_cancel(ctx->timer_handle);
+ ctx->timer_handle=0;
+ }
+
+ nr_stun_message_destroy(&ctx->request);
+ ctx->request = 0;
+
+ nr_stun_message_destroy(&ctx->response);
+ ctx->response = 0;
+
+ memset(&ctx->results, 0, sizeof(ctx->results));
+
+ ctx->mode = 0;
+ ctx->finished_cb = 0;
+ ctx->cb_arg = 0;
+ ctx->request_ct = 0;
+ ctx->timeout_ms = 0;
+
+ ctx->state = NR_STUN_CLIENT_STATE_INITTED;
+
+ return 0;
+}
+
+static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
+ {
+ int _status;
+ nr_stun_client_ctx *ctx=cb_arg;
+ struct timeval now;
+ INT8 ms_waited;
+
+ /* Prevent this timer from being cancelled later */
+ ctx->timer_handle=0;
+
+ /* Shouldn't happen */
+ if(ctx->state==NR_STUN_CLIENT_STATE_CANCELLED)
+ ABORT(R_REJECTED);
+
+ gettimeofday(&now, 0);
+ if (r_timeval_diff_ms(&now, &ctx->timer_set, &ms_waited)) {
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired",ctx->label);
+ }
+ else {
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Timer expired (after %llu ms)",ctx->label, ms_waited);
+ }
+
+ if (ctx->request_ct >= ctx->maximum_transmits) {
+ r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Timed out",ctx->label);
+ ctx->state=NR_STUN_CLIENT_STATE_TIMED_OUT;
+ ABORT(R_FAILED);
+ }
+
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
+ ABORT(R_NOT_PERMITTED);
+
+ /* as a side effect will reset the timer */
+ nr_stun_client_send_request(ctx);
+
+ _status = 0;
+ abort:
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING) {
+ /* Cancel the timer firing */
+ if (ctx->timer_handle){
+ NR_async_timer_cancel(ctx->timer_handle);
+ ctx->timer_handle=0;
+ }
+
+ nr_stun_client_fire_finished_cb(ctx);
+ }
+ return;
+ }
+
+int nr_stun_client_force_retransmit(nr_stun_client_ctx *ctx)
+ {
+ int r,_status;
+
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
+ ABORT(R_NOT_PERMITTED);
+
+ if (ctx->request_ct > ctx->maximum_transmits) {
+ r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Too many retransmit attempts",ctx->label);
+ ABORT(R_FAILED);
+ }
+
+ /* if there is a scheduled retransimt, get rid of the scheduled retransmit
+ * and retransmit immediately */
+ if (ctx->timer_handle) {
+ NR_async_timer_cancel(ctx->timer_handle);
+ ctx->timer_handle=0;
+
+ if (r=nr_stun_client_send_request(ctx))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+
+ return(_status);
+ }
+
+static int nr_stun_client_send_request(nr_stun_client_ctx *ctx)
+ {
+ int r,_status;
+ char string[256];
+
+ if (ctx->state != NR_STUN_CLIENT_STATE_RUNNING)
+ ABORT(R_NOT_PERMITTED);
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Sending check request (my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,ctx->peer_addr.as_string);
+
+ if (ctx->request == 0) {
+ switch (ctx->mode) {
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH:
+ ctx->params.stun_binding_request.nonce = ctx->nonce;
+ ctx->params.stun_binding_request.realm = ctx->realm;
+ assert(0);
+ ABORT(R_INTERNAL);
+ /* TODO(ekr@rtfm.com): Need to implement long-term auth for binding
+ requests */
+ if ((r=nr_stun_build_req_lt_auth(&ctx->params.stun_binding_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH:
+ if ((r=nr_stun_build_req_st_auth(&ctx->params.stun_binding_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH:
+ if ((r=nr_stun_build_req_no_auth(&ctx->params.stun_binding_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_STUN_CLIENT_MODE_KEEPALIVE:
+ if ((r=nr_stun_build_keepalive(&ctx->params.stun_keepalive, &ctx->request)))
+ ABORT(r);
+ break;
+#ifdef USE_STUND_0_96
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96:
+ if ((r=nr_stun_build_req_stund_0_96(&ctx->params.stun_binding_request_stund_0_96, &ctx->request)))
+ ABORT(r);
+ break;
+#endif /* USE_STUND_0_96 */
+
+#ifdef USE_ICE
+ case NR_ICE_CLIENT_MODE_USE_CANDIDATE:
+ if ((r=nr_stun_build_use_candidate(&ctx->params.ice_binding_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_ICE_CLIENT_MODE_BINDING_REQUEST:
+ if ((r=nr_stun_build_req_ice(&ctx->params.ice_binding_request, &ctx->request)))
+ ABORT(r);
+ break;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST:
+ if ((r=nr_stun_build_allocate_request(&ctx->auth_params, &ctx->params.allocate_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_TURN_CLIENT_MODE_REFRESH_REQUEST:
+ if ((r=nr_stun_build_refresh_request(&ctx->auth_params, &ctx->params.refresh_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_TURN_CLIENT_MODE_PERMISSION_REQUEST:
+ if ((r=nr_stun_build_permission_request(&ctx->auth_params, &ctx->params.permission_request, &ctx->request)))
+ ABORT(r);
+ break;
+ case NR_TURN_CLIENT_MODE_SEND_INDICATION:
+ if ((r=nr_stun_build_send_indication(&ctx->params.send_indication, &ctx->request)))
+ ABORT(r);
+ break;
+#endif /* USE_TURN */
+
+ default:
+ assert(0);
+ ABORT(R_FAILED);
+ break;
+ }
+ }
+
+ if (ctx->request->length == 0) {
+ if ((r=nr_stun_encode_message(ctx->request)))
+ ABORT(r);
+ }
+
+ snprintf(string, sizeof(string)-1, "STUN-CLIENT(%s): Sending to %s ", ctx->label, ctx->peer_addr.as_string);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)ctx->request->buffer, ctx->request->length);
+
+ assert(ctx->my_addr.protocol==ctx->peer_addr.protocol);
+
+ if(r=nr_socket_sendto(ctx->sock, ctx->request->buffer, ctx->request->length, 0, &ctx->peer_addr)) {
+ if (r != R_WOULDBLOCK) {
+ ABORT(r);
+ }
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-CLIENT(%s): nr_socket_sendto blocked, treating as dropped packet",ctx->label);
+ }
+
+ ctx->request_ct++;
+
+ if (NR_STUN_GET_TYPE_CLASS(ctx->request->header.type) == NR_CLASS_INDICATION) {
+ /* no need to set the timer because indications don't receive a
+ * response */
+ }
+ else {
+ if (ctx->request_ct >= ctx->maximum_transmits) {
+ /* Reliable transport only get here once. Unreliable get here for
+ * their final timeout. */
+ ctx->timeout_ms += ctx->maximum_transmits_timeout_ms;
+ }
+ else if (ctx->timeout_ms) {
+ /* exponential backoff */
+ ctx->timeout_ms *= ctx->retransmission_backoff_factor;
+ }
+ else {
+ /* initial timeout unreliable transports */
+ ctx->timeout_ms = ctx->rto_ms;
+ }
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Next timer will fire in %u ms",ctx->label, ctx->timeout_ms);
+
+ gettimeofday(&ctx->timer_set, 0);
+
+ assert(ctx->timeout_ms);
+ NR_ASYNC_TIMER_SET(ctx->timeout_ms, nr_stun_client_timer_expired_cb, ctx, &ctx->timer_handle);
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ nr_stun_client_failed(ctx);
+ }
+ return(_status);
+ }
+
+static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
+{
+ *password = (Data*)arg;
+ if (!arg)
+ return(R_NOT_FOUND);
+ return(0);
+}
+
+int nr_stun_transport_addr_check(nr_transport_addr* addr, UINT4 check)
+ {
+ if((check & NR_STUN_TRANSPORT_ADDR_CHECK_WILDCARD) && nr_transport_addr_is_wildcard(addr))
+ return(R_BAD_DATA);
+
+ if ((check & NR_STUN_TRANSPORT_ADDR_CHECK_LOOPBACK) && nr_transport_addr_is_loopback(addr))
+ return(R_BAD_DATA);
+
+ return(0);
+ }
+
+int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
+ {
+ int r,_status;
+ char string[256];
+ char *username = 0;
+ Data *password = 0;
+ nr_stun_message_attribute *attr;
+ nr_transport_addr *mapped_addr = 0;
+ int fail_on_error = 0;
+ UCHAR hmac_key_d[16];
+ Data hmac_key;
+ int compute_lt_key=0;
+ /* TODO(bcampen@mozilla.com): Bug 1023619, refactor this. */
+ int response_matched=0;
+
+ ATTACH_DATA(hmac_key, hmac_key_d);
+
+ if ((ctx->state != NR_STUN_CLIENT_STATE_RUNNING) &&
+ (ctx->state != NR_STUN_CLIENT_STATE_WAITING))
+ ABORT(R_REJECTED);
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Inspecting STUN response (my_addr=%s, peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
+
+ snprintf(string, sizeof(string)-1, "STUN-CLIENT(%s): Received ", ctx->label);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)msg, len);
+
+ /* determine password */
+ switch (ctx->mode) {
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH:
+ compute_lt_key = 1;
+ /* Fall through */
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH:
+ password = ctx->params.stun_binding_request.password;
+ break;
+
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH:
+ /* do nothing */
+ break;
+
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96:
+ /* do nothing */
+ break;
+
+#ifdef USE_ICE
+ case NR_ICE_CLIENT_MODE_BINDING_REQUEST:
+ password = &ctx->params.ice_binding_request.password;
+ break;
+ case NR_ICE_CLIENT_MODE_USE_CANDIDATE:
+ password = &ctx->params.ice_binding_request.password;
+ break;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST:
+ fail_on_error = 1;
+ compute_lt_key = 1;
+ username = ctx->auth_params.username;
+ password = &ctx->auth_params.password;
+ /* do nothing */
+ break;
+ case NR_TURN_CLIENT_MODE_REFRESH_REQUEST:
+ fail_on_error = 1;
+ compute_lt_key = 1;
+ username = ctx->auth_params.username;
+ password = &ctx->auth_params.password;
+ /* do nothing */
+ break;
+ case NR_TURN_CLIENT_MODE_PERMISSION_REQUEST:
+ fail_on_error = 1;
+ compute_lt_key = 1;
+ username = ctx->auth_params.username;
+ password = &ctx->auth_params.password;
+ /* do nothing */
+ break;
+ case NR_TURN_CLIENT_MODE_SEND_INDICATION:
+ /* do nothing -- we just got our DATA-INDICATION */
+ break;
+#endif /* USE_TURN */
+
+ default:
+ assert(0);
+ ABORT(R_FAILED);
+ break;
+ }
+
+ if (compute_lt_key) {
+ if (!ctx->realm || !username) {
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Long-term auth required but no realm/username specified. Randomizing key");
+ /* Fill the key with random bytes to guarantee non-match */
+ if (r=nr_crypto_random_bytes(hmac_key_d, sizeof(hmac_key_d)))
+ ABORT(r);
+ }
+ else {
+ if (r=nr_stun_compute_lt_message_integrity_password(username, ctx->realm,
+ password, &hmac_key))
+ ABORT(r);
+ }
+ password = &hmac_key;
+ }
+
+ if (ctx->response) {
+ nr_stun_message_destroy(&ctx->response);
+ }
+
+ /* TODO(bcampen@mozilla.com): Bug 1023619, refactor this. */
+ if ((r=nr_stun_message_create2(&ctx->response, msg, len)))
+ ABORT(r);
+
+ if ((r=nr_stun_decode_message(ctx->response, nr_stun_client_get_password, password))) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-CLIENT(%s): error decoding response",ctx->label);
+ ABORT(r);
+ }
+
+ /* This will return an error if request and response don't match,
+ which is how we reject responses that match other contexts. */
+ if ((r=nr_stun_receive_message(ctx->request, ctx->response))) {
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Response is not for us",ctx->label);
+ ABORT(r);
+ }
+
+ r_log(NR_LOG_STUN,LOG_INFO,
+ "STUN-CLIENT(%s): Received response; processing",ctx->label);
+ response_matched=1;
+
+/* TODO: !nn! currently using password!=0 to mean that auth is required,
+ * TODO: !nn! but we should probably pass that in explicitly via the
+ * TODO: !nn! usage (ctx->mode?) */
+ if (password) {
+ if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_NONCE, 0)) {
+ if ((r=nr_stun_receive_response_long_term_auth(ctx->response, ctx)))
+ ABORT(r);
+ }
+ else {
+ if ((r=nr_stun_receive_response_short_term_auth(ctx->response)))
+ ABORT(r);
+ }
+ }
+
+ if (NR_STUN_GET_TYPE_CLASS(ctx->response->header.type) == NR_CLASS_RESPONSE) {
+ if ((r=nr_stun_process_success_response(ctx->response)))
+ ABORT(r);
+ }
+ else {
+ if (fail_on_error) {
+ ctx->state = NR_STUN_CLIENT_STATE_FAILED;
+ }
+ /* Note: most times we call process_error_response, we get r != 0.
+
+ However, if the error is to be discarded, we get r == 0, smash
+ the error code, and just keep going.
+ */
+ if ((r=nr_stun_process_error_response(ctx->response, &ctx->error_code))) {
+ ABORT(r);
+ }
+ else {
+ ctx->error_code = 0xffff;
+ /* drop the error on the floor */
+ ABORT(R_FAILED);
+ }
+ }
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Successfully parsed mode=%d",ctx->label,ctx->mode);
+
+/* TODO: !nn! this should be moved to individual message receive/processing sections */
+ switch (ctx->mode) {
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH:
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0))
+ ABORT(R_BAD_DATA);
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+
+ mapped_addr = &ctx->results.stun_binding_response.mapped_addr;
+ break;
+
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0)) {
+ if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MAPPED_ADDRESS, 0)) {
+ /* Compensate for a bug in Google's STUN servers where they always respond with MAPPED-ADDRESS */
+ r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): No XOR-MAPPED-ADDRESS but MAPPED-ADDRESS. Falling back (though server is wrong).", ctx->label);
+ }
+ else {
+ ABORT(R_BAD_DATA);
+ }
+ }
+
+ mapped_addr = &ctx->results.stun_binding_response.mapped_addr;
+ break;
+
+ case NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MAPPED_ADDRESS, 0) && ! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0))
+ ABORT(R_BAD_DATA);
+
+ mapped_addr = &ctx->results.stun_binding_response_stund_0_96.mapped_addr;
+ break;
+
+#ifdef USE_ICE
+ case NR_ICE_CLIENT_MODE_BINDING_REQUEST:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0))
+ ABORT(R_BAD_DATA);
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+
+ mapped_addr = &ctx->results.stun_binding_response.mapped_addr;
+ break;
+ case NR_ICE_CLIENT_MODE_USE_CANDIDATE:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0))
+ ABORT(R_BAD_DATA);
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+
+ mapped_addr = &ctx->results.stun_binding_response.mapped_addr;
+ break;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ case NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0))
+ ABORT(R_BAD_DATA);
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+
+ if (!nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_RELAY_ADDRESS, &attr))
+ ABORT(R_BAD_DATA);
+
+ if ((r=nr_stun_transport_addr_check(&attr->u.relay_address.unmasked,
+ ctx->mapped_addr_check_mask)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(
+ &ctx->results.allocate_response.relay_addr,
+ &attr->u.relay_address.unmasked)))
+ ABORT(r);
+
+ if (!nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_LIFETIME, &attr))
+ ABORT(R_BAD_DATA);
+ ctx->results.allocate_response.lifetime_secs=attr->u.lifetime_secs;
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Received relay address: %s", ctx->label, ctx->results.allocate_response.relay_addr.as_string);
+
+ mapped_addr = &ctx->results.allocate_response.mapped_addr;
+
+ break;
+ case NR_TURN_CLIENT_MODE_REFRESH_REQUEST:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+ if (!nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_LIFETIME, &attr))
+ ABORT(R_BAD_DATA);
+ ctx->results.refresh_response.lifetime_secs=attr->u.lifetime_secs;
+ break;
+ case NR_TURN_CLIENT_MODE_PERMISSION_REQUEST:
+ if (! nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0))
+ ABORT(R_BAD_DATA);
+ break;
+#endif /* USE_TURN */
+
+ default:
+ assert(0);
+ ABORT(R_FAILED);
+ break;
+ }
+
+ /* make sure we have the most up-to-date address from this peer */
+ if (nr_transport_addr_cmp(&ctx->peer_addr, peer_addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ r_log(NR_LOG_STUN,LOG_INFO,"STUN-CLIENT(%s): Peer moved from %s to %s", ctx->label, ctx->peer_addr.as_string, peer_addr->as_string);
+ nr_transport_addr_copy(&ctx->peer_addr, peer_addr);
+ }
+
+ if (mapped_addr) {
+ if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, &attr)) {
+ if ((r=nr_stun_transport_addr_check(&attr->u.xor_mapped_address.unmasked,
+ ctx->mapped_addr_check_mask)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(mapped_addr, &attr->u.xor_mapped_address.unmasked)))
+ ABORT(r);
+ }
+ else if (nr_stun_message_has_attribute(ctx->response, NR_STUN_ATTR_MAPPED_ADDRESS, &attr)) {
+ if ((r=nr_stun_transport_addr_check(&attr->u.mapped_address,
+ ctx->mapped_addr_check_mask)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(mapped_addr, &attr->u.mapped_address)))
+ ABORT(r);
+ }
+ else
+ ABORT(R_BAD_DATA);
+
+ // STUN doesn't distinguish protocol in mapped address, therefore
+ // assign used protocol from peer_addr
+ if (mapped_addr->protocol!=peer_addr->protocol){
+ mapped_addr->protocol=peer_addr->protocol;
+ nr_transport_addr_fmt_addr_string(mapped_addr);
+ }
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-CLIENT(%s): Received mapped address: %s", ctx->label, mapped_addr->as_string);
+ }
+
+ ctx->state=NR_STUN_CLIENT_STATE_DONE;
+
+ _status=0;
+ abort:
+ if(_status && response_matched){
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-CLIENT(%s): Error processing response: %s, stun error code %d.", ctx->label, nr_strerror(_status), (int)ctx->error_code);
+ }
+
+ if ((ctx->state != NR_STUN_CLIENT_STATE_RUNNING) &&
+ (ctx->state != NR_STUN_CLIENT_STATE_WAITING)) {
+ /* Cancel the timer firing */
+ if (ctx->timer_handle) {
+ NR_async_timer_cancel(ctx->timer_handle);
+ ctx->timer_handle = 0;
+ }
+
+ nr_stun_client_fire_finished_cb(ctx);
+ }
+
+ return(_status);
+ }
+
+int nr_stun_client_ctx_destroy(nr_stun_client_ctx **ctxp)
+ {
+ nr_stun_client_ctx *ctx;
+
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ ctx=*ctxp;
+ *ctxp=0;
+
+ nr_stun_client_reset(ctx);
+
+ RFREE(ctx->nonce);
+ RFREE(ctx->realm);
+
+ RFREE(ctx->label);
+ RFREE(ctx);
+
+ return(0);
+ }
+
+
+int nr_stun_client_cancel(nr_stun_client_ctx *ctx)
+ {
+ /* Cancel the timer firing */
+ if (ctx->timer_handle){
+ NR_async_timer_cancel(ctx->timer_handle);
+ ctx->timer_handle=0;
+ }
+
+ /* Mark cancelled so we ignore any returned messsages */
+ ctx->state=NR_STUN_CLIENT_STATE_CANCELLED;
+ return(0);
+}
+
+int nr_stun_client_wait(nr_stun_client_ctx *ctx)
+ {
+ nr_stun_client_cancel(ctx);
+ ctx->state=NR_STUN_CLIENT_STATE_WAITING;
+
+ ctx->request_ct = ctx->maximum_transmits;
+ ctx->timeout_ms = ctx->maximum_transmits_timeout_ms;
+ NR_ASYNC_TIMER_SET(ctx->timeout_ms, nr_stun_client_timer_expired_cb, ctx, &ctx->timer_handle);
+
+ return(0);
+ }
+
+int nr_stun_client_failed(nr_stun_client_ctx *ctx)
+ {
+ nr_stun_client_cancel(ctx);
+ ctx->state=NR_STUN_CLIENT_STATE_FAILED;
+ nr_stun_client_fire_finished_cb(ctx);
+ return(0);
+ }
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.h b/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.h
new file mode 100644
index 000000000..179f16cba
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_client_ctx.h
@@ -0,0 +1,199 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_client_ctx_h
+#define _stun_client_ctx_h
+
+/* forward declaration */
+typedef struct nr_stun_client_ctx_ nr_stun_client_ctx;
+
+#include "stun.h"
+
+/* Checklist for adding new STUN transaction types
+
+ 1. Add new method type in stun.h (NR_METHOD_*)
+ 2. Add new MSGs in stun.h (NR_STUN_MSG_*)
+ 3. Add new messages to stun_util.c:nr_stun_msg_type
+ 4. Add new request type to stun_build.h
+ 4. Add new message builder to stun_build.c
+ 5. Add new response type to stun_client_ctx.h
+ 6. Add new arm to stun_client_ctx.c:nr_stun_client_send_request
+ 7. Add new arms to nr_stun_client_process_response
+ 8. Add new arms to stun_hint.c:nr_is_stun_message
+*/
+
+
+
+
+typedef union nr_stun_client_params_ {
+
+ nr_stun_client_stun_binding_request_params stun_binding_request;
+ nr_stun_client_stun_keepalive_params stun_keepalive;
+#ifdef USE_STUND_0_96
+ nr_stun_client_stun_binding_request_stund_0_96_params stun_binding_request_stund_0_96;
+#endif /* USE_STUND_0_96 */
+
+#ifdef USE_ICE
+ nr_stun_client_ice_binding_request_params ice_binding_request;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ nr_stun_client_allocate_request_params allocate_request;
+ nr_stun_client_refresh_request_params refresh_request;
+ nr_stun_client_permission_request_params permission_request;
+ nr_stun_client_send_indication_params send_indication;
+#endif /* USE_TURN */
+
+} nr_stun_client_params;
+
+typedef struct nr_stun_client_stun_binding_response_results_ {
+ nr_transport_addr mapped_addr;
+} nr_stun_client_stun_binding_response_results;
+
+typedef struct nr_stun_client_stun_binding_response_stund_0_96_results_ {
+ nr_transport_addr mapped_addr;
+} nr_stun_client_stun_binding_response_stund_0_96_results;
+
+#ifdef USE_ICE
+typedef struct nr_stun_client_ice_use_candidate_results_ {
+#ifdef WIN32 // silly VC++ gives error if no members
+ int dummy;
+#endif
+} nr_stun_client_ice_use_candidate_results;
+
+typedef struct nr_stun_client_ice_binding_response_results_ {
+ nr_transport_addr mapped_addr;
+} nr_stun_client_ice_binding_response_results;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+typedef struct nr_stun_client_allocate_response_results_ {
+ nr_transport_addr relay_addr;
+ nr_transport_addr mapped_addr;
+ UINT4 lifetime_secs;
+} nr_stun_client_allocate_response_results;
+
+typedef struct nr_stun_client_refresh_response_results_ {
+ UINT4 lifetime_secs;
+} nr_stun_client_refresh_response_results;
+
+typedef struct nr_stun_client_permission_response_results_ {
+ UINT4 lifetime_secs;
+} nr_stun_client_permission_response_results;
+
+#endif /* USE_TURN */
+
+typedef union nr_stun_client_results_ {
+ nr_stun_client_stun_binding_response_results stun_binding_response;
+ nr_stun_client_stun_binding_response_stund_0_96_results stun_binding_response_stund_0_96;
+
+#ifdef USE_ICE
+ nr_stun_client_ice_use_candidate_results ice_use_candidate;
+ nr_stun_client_ice_binding_response_results ice_binding_response;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ nr_stun_client_allocate_response_results allocate_response;
+ nr_stun_client_refresh_response_results refresh_response;
+#endif /* USE_TURN */
+} nr_stun_client_results;
+
+struct nr_stun_client_ctx_ {
+ int state;
+#define NR_STUN_CLIENT_STATE_INITTED 0
+#define NR_STUN_CLIENT_STATE_RUNNING 1
+#define NR_STUN_CLIENT_STATE_DONE 2
+#define NR_STUN_CLIENT_STATE_FAILED 3
+#define NR_STUN_CLIENT_STATE_TIMED_OUT 4
+#define NR_STUN_CLIENT_STATE_CANCELLED 5
+#define NR_STUN_CLIENT_STATE_WAITING 6
+
+ int mode;
+#define NR_STUN_CLIENT_MODE_BINDING_REQUEST_SHORT_TERM_AUTH 1
+#define NR_STUN_CLIENT_MODE_BINDING_REQUEST_LONG_TERM_AUTH 2
+#define NR_STUN_CLIENT_MODE_BINDING_REQUEST_NO_AUTH 3
+#define NR_STUN_CLIENT_MODE_KEEPALIVE 4
+#define NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96 5
+#ifdef USE_ICE
+#define NR_ICE_CLIENT_MODE_USE_CANDIDATE 10
+#define NR_ICE_CLIENT_MODE_BINDING_REQUEST 11
+#endif /* USE_ICE */
+#ifdef USE_TURN
+#define NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST 20
+#define NR_TURN_CLIENT_MODE_REFRESH_REQUEST 21
+#define NR_TURN_CLIENT_MODE_SEND_INDICATION 22
+#define NR_TURN_CLIENT_MODE_DATA_INDICATION 24
+#define NR_TURN_CLIENT_MODE_PERMISSION_REQUEST 25
+#endif /* USE_TURN */
+
+ char *label;
+ nr_transport_addr my_addr;
+ nr_transport_addr peer_addr;
+ nr_socket *sock;
+ nr_stun_client_auth_params auth_params;
+ nr_stun_client_params params;
+ nr_stun_client_results results;
+ char *nonce;
+ char *realm;
+ void *timer_handle;
+ int request_ct;
+ UINT4 rto_ms; /* retransmission time out */
+ double retransmission_backoff_factor;
+ UINT4 maximum_transmits;
+ UINT4 maximum_transmits_timeout_ms;
+ UINT4 mapped_addr_check_mask; /* What checks to run on mapped addresses */
+ int timeout_ms;
+ struct timeval timer_set;
+ int retry_ct;
+ NR_async_cb finished_cb;
+ void *cb_arg;
+ nr_stun_message *request;
+ nr_stun_message *response;
+ UINT2 error_code;
+};
+
+int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp);
+int nr_stun_client_start(nr_stun_client_ctx *ctx, int mode, NR_async_cb finished_cb, void *cb_arg);
+int nr_stun_client_restart(nr_stun_client_ctx *ctx);
+int nr_stun_client_force_retransmit(nr_stun_client_ctx *ctx);
+int nr_stun_client_reset(nr_stun_client_ctx *ctx);
+int nr_stun_client_ctx_destroy(nr_stun_client_ctx **ctxp);
+int nr_stun_transport_addr_check(nr_transport_addr* addr, UINT4 mask);
+int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr);
+int nr_stun_client_cancel(nr_stun_client_ctx *ctx);
+int nr_stun_client_wait(nr_stun_client_ctx *ctx);
+int nr_stun_client_failed(nr_stun_client_ctx *ctx);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_codec.c b/media/mtransport/third_party/nICEr/src/stun/stun_codec.c
new file mode 100644
index 000000000..6faab70de
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_codec.c
@@ -0,0 +1,1522 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_codec.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else /* UNIX */
+#include <string.h>
+#endif /* end UNIX */
+#include <assert.h>
+#include <stddef.h>
+
+#include "nr_api.h"
+#include "stun.h"
+#include "byteorder.h"
+#include "r_crc32.h"
+#include "nr_crypto.h"
+#include "mbslen.h"
+
+#define NR_STUN_IPV4_FAMILY 0x01
+#define NR_STUN_IPV6_FAMILY 0x02
+
+#define SKIP_ATTRIBUTE_DECODE -1
+
+static int nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info);
+
+static int nr_stun_fix_attribute_ordering(nr_stun_message *msg);
+
+static int nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset);
+static int nr_stun_encode_htonl(UINT4 data, int buflen, UCHAR *buf, int *offset);
+static int nr_stun_encode_htonll(UINT8 data, int buflen, UCHAR *buf, int *offset);
+static int nr_stun_encode(UCHAR *data, int length, int buflen, UCHAR *buf, int *offset);
+
+static int nr_stun_decode_htons(UCHAR *buf, int buflen, int *offset, UINT2 *data);
+static int nr_stun_decode_htonl(UCHAR *buf, int buflen, int *offset, UINT4 *data);
+static int nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data);
+static int nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data);
+
+static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
+
+static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+static int
+nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
+
+
+int
+nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
+{
+ UINT2 d = htons(data);
+
+ if (*offset + sizeof(d) >= buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd >= %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&buf[*offset], &d, sizeof(d));
+ *offset += sizeof(d);
+
+ return 0;
+}
+
+int
+nr_stun_encode_htonl(UINT4 data, int buflen, UCHAR *buf, int *offset)
+{
+ UINT4 d = htonl(data);
+
+ if (*offset + sizeof(d) > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&buf[*offset], &d, sizeof(d));
+ *offset += sizeof(d);
+
+ return 0;
+}
+
+int
+nr_stun_encode_htonll(UINT8 data, int buflen, UCHAR *buf, int *offset)
+{
+ UINT8 d = nr_htonll(data);
+
+ if (*offset + sizeof(d) > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&buf[*offset], &d, sizeof(d));
+ *offset += sizeof(d);
+
+ return 0;
+}
+
+int
+nr_stun_encode(UCHAR *data, int length, int buflen, UCHAR *buf, int *offset)
+{
+ if (*offset + length > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d > %d", *offset, length, buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&buf[*offset], data, length);
+ *offset += length;
+
+ return 0;
+}
+
+
+int
+nr_stun_decode_htons(UCHAR *buf, int buflen, int *offset, UINT2 *data)
+{
+ UINT2 d;
+
+ if (*offset + sizeof(d) > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&d, &buf[*offset], sizeof(d));
+ *offset += sizeof(d);
+ *data = htons(d);
+
+ return 0;
+}
+
+int
+nr_stun_decode_htonl(UCHAR *buf, int buflen, int *offset, UINT4 *data)
+{
+ UINT4 d;
+
+ if (*offset + sizeof(d) > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&d, &buf[*offset], sizeof(d));
+ *offset += sizeof(d);
+ *data = htonl(d);
+
+ return 0;
+}
+
+int
+nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data)
+{
+ UINT8 d;
+
+ if (*offset + sizeof(d) > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(&d, &buf[*offset], sizeof(d));
+ *offset += sizeof(d);
+ *data = nr_htonll(d);
+
+ return 0;
+}
+
+int
+nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data)
+{
+ if (*offset + length > buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d > %d", *offset, length, buflen);
+ return R_BAD_DATA;
+ }
+
+ memcpy(data, &buf[*offset], length);
+ *offset += length;
+
+ return 0;
+}
+
+int
+nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars)
+{
+ int _status;
+ char *s = data;
+ size_t nchars;
+
+ if (len > max_bytes) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "%s is too large: %d bytes", attr_info->name, len);
+ ABORT(R_FAILED);
+ }
+
+ if (max_chars >= 0) {
+ if (mbslen(s, &nchars)) {
+ /* who knows what to do, just assume everything is working ok */
+ }
+ else if (nchars > max_chars) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "%s is too large: %zd characters", attr_info->name, nchars);
+ ABORT(R_FAILED);
+ }
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+int
+nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data)
+{
+ int r,_status;
+ nr_stun_attr_error_code *ec = data;
+
+ if (ec->number < 300 || ec->number > 699)
+ ABORT(R_FAILED);
+
+ if ((r=nr_stun_attr_string_illegal(attr_info, strlen(ec->reason), ec->reason, NR_STUN_MAX_ERROR_CODE_REASON_BYTES, NR_STUN_MAX_ERROR_CODE_REASON_CHARS)))
+ ABORT(r);
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+int
+nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data)
+{
+ return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_NONCE_BYTES, NR_STUN_MAX_NONCE_CHARS);
+}
+
+int
+nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data)
+{
+ return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_REALM_BYTES, NR_STUN_MAX_REALM_CHARS);
+}
+
+int
+nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data)
+{
+ return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_SERVER_BYTES, NR_STUN_MAX_SERVER_CHARS);
+}
+
+int
+nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data)
+{
+ return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_USERNAME_BYTES, -1);
+}
+
+static int
+nr_stun_attr_codec_UCHAR_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %u", msg, attr_info->name, *(UCHAR*)data);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UCHAR_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+ UINT4 tmp = *((UCHAR *)data);
+ tmp <<= 24;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(sizeof(UINT4) , buflen, buf, &offset)
+ || nr_stun_encode_htonl(tmp , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UCHAR_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ UINT4 tmp;
+
+ if (attrlen != sizeof(UINT4)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Integer is illegal size: %d", attrlen);
+ return R_FAILED;
+ }
+
+ if (nr_stun_decode_htonl(buf, buflen, &offset, &tmp))
+ return R_FAILED;
+
+ *((UCHAR *)data) = (tmp >> 24) & 0xff;
+
+ return 0;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_UCHAR = {
+ "UCHAR",
+ nr_stun_attr_codec_UCHAR_print,
+ nr_stun_attr_codec_UCHAR_encode,
+ nr_stun_attr_codec_UCHAR_decode
+};
+
+static int
+nr_stun_attr_codec_UINT4_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %u", msg, attr_info->name, *(UINT4*)data);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UINT4_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(sizeof(UINT4) , buflen, buf, &offset)
+ || nr_stun_encode_htonl(*(UINT4*)data , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UINT4_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ if (attrlen != sizeof(UINT4)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Integer is illegal size: %d", attrlen);
+ return R_FAILED;
+ }
+
+ if (nr_stun_decode_htonl(buf, buflen, &offset, (UINT4*)data))
+ return R_FAILED;
+
+ return 0;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_UINT4 = {
+ "UINT4",
+ nr_stun_attr_codec_UINT4_print,
+ nr_stun_attr_codec_UINT4_encode,
+ nr_stun_attr_codec_UINT4_decode
+};
+
+static int
+nr_stun_attr_codec_UINT8_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %llu", msg, attr_info->name, *(UINT8*)data);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UINT8_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(sizeof(UINT8) , buflen, buf, &offset)
+ || nr_stun_encode_htonll(*(UINT8*)data , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_UINT8_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ if (attrlen != sizeof(UINT8)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Integer is illegal size: %d", attrlen);
+ return R_FAILED;
+ }
+
+ if (nr_stun_decode_htonll(buf, buflen, &offset, (UINT8*)data))
+ return R_FAILED;
+
+ return 0;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_UINT8 = {
+ "UINT8",
+ nr_stun_attr_codec_UINT8_print,
+ nr_stun_attr_codec_UINT8_encode,
+ nr_stun_attr_codec_UINT8_decode
+};
+
+static int
+nr_stun_attr_codec_addr_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s", msg, attr_info->name, ((nr_transport_addr*)data)->as_string);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_addr_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int r,_status;
+ int start = offset;
+ nr_transport_addr *addr = data;
+ UCHAR pad = '\0';
+ UCHAR family;
+
+ if ((r=nr_stun_encode_htons(attr_info->type, buflen, buf, &offset)))
+ ABORT(r);
+
+ switch (addr->ip_version) {
+ case NR_IPV4:
+ family = NR_STUN_IPV4_FAMILY;
+ if (nr_stun_encode_htons(8 , buflen, buf, &offset)
+ || nr_stun_encode(&pad, 1 , buflen, buf, &offset)
+ || nr_stun_encode(&family, 1 , buflen, buf, &offset)
+ || nr_stun_encode_htons(ntohs(addr->u.addr4.sin_port), buflen, buf, &offset)
+ || nr_stun_encode_htonl(ntohl(addr->u.addr4.sin_addr.s_addr), buflen, buf, &offset))
+ ABORT(R_FAILED);
+ break;
+
+ case NR_IPV6:
+ family = NR_STUN_IPV6_FAMILY;
+ if (nr_stun_encode_htons(20 , buflen, buf, &offset)
+ || nr_stun_encode(&pad, 1 , buflen, buf, &offset)
+ || nr_stun_encode(&family, 1 , buflen, buf, &offset)
+ || nr_stun_encode_htons(ntohs(addr->u.addr6.sin6_port), buflen, buf, &offset)
+ || nr_stun_encode(addr->u.addr6.sin6_addr.s6_addr, 16, buflen, buf, &offset))
+ ABORT(R_FAILED);
+ break;
+
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ *attrlen = offset - start;
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+static int
+nr_stun_attr_codec_addr_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ UCHAR pad;
+ UCHAR family;
+ UINT2 port;
+ UINT4 addr4;
+ struct in6_addr addr6;
+ nr_transport_addr *result = data;
+
+ if (nr_stun_decode(1, buf, buflen, &offset, &pad)
+ || nr_stun_decode(1, buf, buflen, &offset, &family))
+ ABORT(R_FAILED);
+
+ switch (family) {
+ case NR_STUN_IPV4_FAMILY:
+ if (attrlen != 8) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal attribute length: %d", attrlen);
+ ABORT(R_FAILED);
+ }
+
+ if (nr_stun_decode_htons(buf, buflen, &offset, &port)
+ || nr_stun_decode_htonl(buf, buflen, &offset, &addr4))
+ ABORT(R_FAILED);
+
+ if (nr_ip4_port_to_transport_addr(addr4, port, IPPROTO_UDP, result))
+ ABORT(R_FAILED);
+ break;
+
+ case NR_STUN_IPV6_FAMILY:
+ if (attrlen != 20) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal attribute length: %d", attrlen);
+ ABORT(R_FAILED);
+ }
+
+ if (nr_stun_decode_htons(buf, buflen, &offset, &port)
+ || nr_stun_decode(16, buf, buflen, &offset, addr6.s6_addr))
+ ABORT(R_FAILED);
+
+ if (nr_ip6_port_to_transport_addr(&addr6, port, IPPROTO_UDP, result))
+ ABORT(R_FAILED);
+ break;
+
+ default:
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal address family: %d", family);
+ ABORT(R_FAILED);
+ break;
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_addr = {
+ "addr",
+ nr_stun_attr_codec_addr_print,
+ nr_stun_attr_codec_addr_encode,
+ nr_stun_attr_codec_addr_decode
+};
+
+static int
+nr_stun_attr_codec_data_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_data *d = data;
+ r_dump(NR_LOG_STUN, LOG_DEBUG, attr_info->name, (char*)d->data, d->length);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_data_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ nr_stun_attr_data *d = data;
+ int start = offset;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(d->length , buflen, buf, &offset)
+ || nr_stun_encode(d->data, d->length , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_data_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ nr_stun_attr_data *result = data;
+
+ /* -1 because it is going to be null terminated just to be safe */
+ if (attrlen >= (sizeof(result->data) - 1)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Too much data: %d bytes", attrlen);
+ ABORT(R_FAILED);
+ }
+
+ if (nr_stun_decode(attrlen, buf, buflen, &offset, result->data))
+ ABORT(R_FAILED);
+
+ result->length = attrlen;
+ result->data[attrlen] = '\0'; /* just to be nice */
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_data = {
+ "data",
+ nr_stun_attr_codec_data_print,
+ nr_stun_attr_codec_data_encode,
+ nr_stun_attr_codec_data_decode
+};
+
+static int
+nr_stun_attr_codec_error_code_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_error_code *error_code = data;
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %d %s",
+ msg, attr_info->name, error_code->number,
+ error_code->reason);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_error_code_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ nr_stun_attr_error_code *error_code = data;
+ int start = offset;
+ int length = strlen(error_code->reason);
+ UCHAR pad[2] = { 0 };
+ UCHAR class = error_code->number / 100;
+ UCHAR number = error_code->number % 100;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(4 + length , buflen, buf, &offset)
+ || nr_stun_encode(pad, 2 , buflen, buf, &offset)
+ || nr_stun_encode(&class, 1 , buflen, buf, &offset)
+ || nr_stun_encode(&number, 1 , buflen, buf, &offset)
+ || nr_stun_encode((UCHAR*)error_code->reason, length, buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_error_code_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ nr_stun_attr_error_code *result = data;
+ UCHAR pad[2];
+ UCHAR class;
+ UCHAR number;
+ int size_reason;
+
+ if (nr_stun_decode(2, buf, buflen, &offset, pad)
+ || nr_stun_decode(1, buf, buflen, &offset, &class)
+ || nr_stun_decode(1, buf, buflen, &offset, &number))
+ ABORT(R_FAILED);
+
+ result->number = (class * 100) + number;
+
+ size_reason = attrlen - 4;
+
+ /* -1 because the string will be null terminated */
+ if (size_reason > (sizeof(result->reason) - 1)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Reason is too large, truncating");
+ /* don't fail, but instead truncate the reason */
+ size_reason = sizeof(result->reason) - 1;
+ }
+
+ if (nr_stun_decode(size_reason, buf, buflen, &offset, (UCHAR*)result->reason))
+ ABORT(R_FAILED);
+ result->reason[size_reason] = '\0';
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_error_code = {
+ "error_code",
+ nr_stun_attr_codec_error_code_print,
+ nr_stun_attr_codec_error_code_encode,
+ nr_stun_attr_codec_error_code_decode
+};
+
+static int
+nr_stun_attr_codec_fingerprint_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_fingerprint *fingerprint = data;
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %08x", msg, attr_info->name, fingerprint->checksum);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_fingerprint_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ UINT4 checksum;
+ nr_stun_attr_fingerprint *fingerprint = data;
+ nr_stun_message_header *header = (nr_stun_message_header*)buf;
+
+ /* the length must include the FINGERPRINT attribute when computing
+ * the fingerprint */
+ header->length = ntohs(header->length);
+ header->length += 8; /* Fingerprint */
+ header->length = htons(header->length);
+
+ if (r_crc32((char*)buf, offset, &checksum)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Unable to compute fingerprint");
+ return R_FAILED;
+ }
+
+ fingerprint->checksum = checksum ^ 0x5354554e;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
+
+ fingerprint->valid = 1;
+ return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
+}
+
+static int
+nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int r,_status;
+ nr_stun_attr_fingerprint *fingerprint = data;
+ nr_stun_message_header *header = (nr_stun_message_header*)buf;
+ int length;
+ UINT4 checksum;
+
+ if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
+ ABORT(r);
+
+ offset -= 4; /* rewind to before the length and type fields */
+
+ /* the length must include the FINGERPRINT attribute when computing
+ * the fingerprint */
+ length = offset; /* right before FINGERPRINT */
+ length -= sizeof(*header); /* remove header length */
+ length += 8; /* add length of Fingerprint */
+ header->length = htons(length);
+
+ /* make sure FINGERPRINT is final attribute in message */
+ assert(length + sizeof(*header) == buflen);
+
+ if (r_crc32((char*)buf, offset, &checksum)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Unable to compute fingerprint");
+ ABORT(R_FAILED);
+ }
+
+ fingerprint->valid = (fingerprint->checksum == (checksum ^ 0x5354554e));
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", (checksum ^ 0x5354554e));
+ if (! fingerprint->valid)
+ r_log(NR_LOG_STUN, LOG_WARNING, "Invalid FINGERPRINT %08x", fingerprint->checksum);
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_fingerprint = {
+ "fingerprint",
+ nr_stun_attr_codec_fingerprint_print,
+ nr_stun_attr_codec_fingerprint_encode,
+ nr_stun_attr_codec_fingerprint_decode
+};
+
+static int
+nr_stun_attr_codec_flag_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: on", msg, attr_info->name);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_flag_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(0 , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_flag_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ if (attrlen != 0) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal flag length: %d", attrlen);
+ return R_FAILED;
+ }
+
+ return 0;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_flag = {
+ "flag",
+ nr_stun_attr_codec_flag_print,
+ nr_stun_attr_codec_flag_encode,
+ nr_stun_attr_codec_flag_decode
+};
+
+static int
+nr_stun_attr_codec_message_integrity_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_message_integrity *integrity = data;
+ r_dump(NR_LOG_STUN, LOG_DEBUG, attr_info->name, (char*)integrity->hash, sizeof(integrity->hash));
+ return 0;
+}
+
+static int
+nr_stun_compute_message_integrity(UCHAR *buf, int offset, UCHAR *password, int passwordlen, UCHAR *computedHMAC)
+{
+ int r,_status;
+ UINT2 hold;
+ UINT2 length;
+ nr_stun_message_header *header;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Computing MESSAGE-INTEGRITY");
+
+ header = (nr_stun_message_header*)buf;
+ hold = header->length;
+
+ /* adjust the length of the message */
+ length = offset;
+ length -= sizeof(*header);
+ length += 24; /* for MESSAGE-INTEGRITY attribute */
+ header->length = htons(length);
+
+ if ((r=nr_crypto_hmac_sha1((UCHAR*)password, passwordlen,
+ buf, offset, computedHMAC)))
+ ABORT(r);
+
+ r_dump(NR_LOG_STUN, LOG_DEBUG, "Computed MESSAGE-INTEGRITY ", (char*)computedHMAC, 20);
+
+ _status=0;
+ abort:
+ header->length = hold;
+ return _status;
+}
+
+static int
+nr_stun_attr_codec_message_integrity_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+ nr_stun_attr_message_integrity *integrity = data;
+
+ if (nr_stun_compute_message_integrity(buf, offset, integrity->password, integrity->passwordlen, integrity->hash))
+ return R_FAILED;
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(sizeof(integrity->hash) , buflen, buf, &offset)
+ || nr_stun_encode(integrity->hash, sizeof(integrity->hash) , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_message_integrity_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ int start;
+ nr_stun_attr_message_integrity *result = data;
+ UCHAR computedHMAC[20];
+
+ result->valid = 0;
+
+ if (attrlen != 20) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "%s must be 20 bytes, not %d", attr_info->name, attrlen);
+ ABORT(R_FAILED);
+ }
+
+ start = offset - 4; /* rewind to before the length and type fields */
+ if (start < 0)
+ ABORT(R_INTERNAL);
+
+ if (nr_stun_decode(attrlen, buf, buflen, &offset, result->hash))
+ ABORT(R_FAILED);
+
+ if (result->unknown_user) {
+ result->valid = 0;
+ }
+ else {
+ if (nr_stun_compute_message_integrity(buf, start, result->password, result->passwordlen, computedHMAC))
+ ABORT(R_FAILED);
+
+ assert(sizeof(computedHMAC) == sizeof(result->hash));
+
+ result->valid = (memcmp(computedHMAC, result->hash, 20) == 0);
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_message_integrity = {
+ "message_integrity",
+ nr_stun_attr_codec_message_integrity_print,
+ nr_stun_attr_codec_message_integrity_encode,
+ nr_stun_attr_codec_message_integrity_decode
+};
+
+static int
+nr_stun_attr_codec_noop_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ return SKIP_ATTRIBUTE_DECODE;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_noop = {
+ "NOOP",
+ 0, /* ignore, never print these attributes */
+ 0, /* ignore, never encode these attributes */
+ nr_stun_attr_codec_noop_decode
+};
+
+static int
+nr_stun_attr_codec_quoted_string_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s",
+ msg, attr_info->name, (char*)data);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_quoted_string_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+//TODO: !nn! syntax check, conversion if not quoted already?
+//We'll just restrict this in the API -- EKR
+ return nr_stun_attr_codec_string.encode(attr_info, data, offset, buflen, buf, attrlen);
+}
+
+static int
+nr_stun_attr_codec_quoted_string_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+//TODO: !nn! I don't see any need to unquote this but we may
+//find one later -- EKR
+ return nr_stun_attr_codec_string.decode(attr_info, attrlen, buf, offset, buflen, data);
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_quoted_string = {
+ "quoted_string",
+ nr_stun_attr_codec_quoted_string_print,
+ nr_stun_attr_codec_quoted_string_encode,
+ nr_stun_attr_codec_quoted_string_decode
+};
+
+static int
+nr_stun_attr_codec_string_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s",
+ msg, attr_info->name, (char*)data);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_string_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int start = offset;
+ char *str = data;
+ int length = strlen(str);
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(length , buflen, buf, &offset)
+ || nr_stun_encode((UCHAR*)str, length , buflen, buf, &offset))
+ return R_FAILED;
+
+ *attrlen = offset - start;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_string_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ char *result = data;
+
+ /* actual enforcement of the specific string size happens elsewhere */
+ if (attrlen >= NR_STUN_MAX_STRING_SIZE) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "String is too large: %d bytes", attrlen);
+ ABORT(R_FAILED);
+ }
+
+ if (nr_stun_decode(attrlen, buf, buflen, &offset, (UCHAR*)result))
+ ABORT(R_FAILED);
+ result[attrlen] = '\0'; /* just to be nice */
+
+ if (strlen(result) != attrlen) {
+ /* stund 0.96 sends a final null in the Server attribute, so
+ * only error if the null appears anywhere else in a string */
+ if (strlen(result) != attrlen-1) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Error in string: %zd/%d", strlen(result), attrlen);
+ ABORT(R_FAILED);
+ }
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_string = {
+ "string",
+ nr_stun_attr_codec_string_print,
+ nr_stun_attr_codec_string_encode,
+ nr_stun_attr_codec_string_decode
+};
+
+static int
+nr_stun_attr_codec_unknown_attributes_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_unknown_attributes *unknown_attributes = data;
+ char type[9];
+ char str[64 + (NR_STUN_MAX_UNKNOWN_ATTRIBUTES * sizeof(type))];
+ int i;
+
+ snprintf(str, sizeof(str), "%s %s:", msg, attr_info->name);
+ for (i = 0; i < unknown_attributes->num_attributes; ++i) {
+ snprintf(type, sizeof(type), "%s 0x%04x", ((i>0)?",":""), unknown_attributes->attribute[i]);
+ strlcat(str, type, sizeof(str));
+ }
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s", str);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_unknown_attributes_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ int _status;
+ int start = offset;
+ nr_stun_attr_unknown_attributes *unknown_attributes = data;
+ int length = (2 * unknown_attributes->num_attributes);
+ int i;
+
+ if (unknown_attributes->num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Too many UNKNOWN-ATTRIBUTES: %d", unknown_attributes->num_attributes);
+ ABORT(R_FAILED);
+ }
+
+ if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset)
+ || nr_stun_encode_htons(length , buflen, buf, &offset))
+ ABORT(R_FAILED);
+
+ for (i = 0; i < unknown_attributes->num_attributes; ++i) {
+ if (nr_stun_encode_htons(unknown_attributes->attribute[i], buflen, buf, &offset))
+ ABORT(R_FAILED);
+ }
+
+ *attrlen = offset - start;
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+static int
+nr_stun_attr_codec_unknown_attributes_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int _status;
+ nr_stun_attr_unknown_attributes *unknown_attributes = data;
+ int i;
+ UINT2 *a;
+
+ if ((attrlen % 4) != 0) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attribute is illegal size: %d", attrlen);
+ ABORT(R_REJECTED);
+ }
+
+ unknown_attributes->num_attributes = attrlen / 2;
+
+ if (unknown_attributes->num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Too many UNKNOWN-ATTRIBUTES: %d", unknown_attributes->num_attributes);
+ ABORT(R_REJECTED);
+ }
+
+ for (i = 0; i < unknown_attributes->num_attributes; ++i) {
+ a = &(unknown_attributes->attribute[i]);
+ if (nr_stun_decode_htons(buf, buflen, &offset, a))
+ return R_FAILED;
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_unknown_attributes = {
+ "unknown_attributes",
+ nr_stun_attr_codec_unknown_attributes_print,
+ nr_stun_attr_codec_unknown_attributes_encode,
+ nr_stun_attr_codec_unknown_attributes_decode
+};
+
+static int
+nr_stun_attr_codec_xor_mapped_address_print(nr_stun_attr_info *attr_info, char *msg, void *data)
+{
+ nr_stun_attr_xor_mapped_address *xor_mapped_address = data;
+ r_log(NR_LOG_STUN, LOG_DEBUG, "%s %s: %s (unmasked) %s (masked)",
+ msg, attr_info->name,
+ xor_mapped_address->unmasked.as_string,
+ xor_mapped_address->masked.as_string);
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_xor_mapped_address_encode(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen)
+{
+ nr_stun_attr_xor_mapped_address *xor_mapped_address = data;
+ nr_stun_message_header *header = (nr_stun_message_header*)buf;
+ UINT4 magic_cookie;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Unmasked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->unmasked.as_string);
+
+ /* this needs to be the magic cookie in the header and not
+ * the MAGIC_COOKIE constant because if we're talking to
+ * older servers (that don't have a magic cookie) they use
+ * message ID for this */
+ magic_cookie = ntohl(header->magic_cookie);
+
+ nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->unmasked, &xor_mapped_address->masked);
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Masked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->masked.as_string);
+
+ if (nr_stun_attr_codec_addr.encode(attr_info, &xor_mapped_address->masked, offset, buflen, buf, attrlen))
+ return R_FAILED;
+
+ return 0;
+}
+
+static int
+nr_stun_attr_codec_xor_mapped_address_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+{
+ int r,_status;
+ nr_stun_attr_xor_mapped_address *xor_mapped_address = data;
+ nr_stun_message_header *header = (nr_stun_message_header*)buf;
+ UINT4 magic_cookie;
+
+ if ((r=nr_stun_attr_codec_addr.decode(attr_info, attrlen, buf, offset, buflen, &xor_mapped_address->masked)))
+ ABORT(r);
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Masked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->masked.as_string);
+
+ /* this needs to be the magic cookie in the header and not
+ * the MAGIC_COOKIE constant because if we're talking to
+ * older servers (that don't have a magic cookie) they use
+ * message ID for this */
+ magic_cookie = ntohl(header->magic_cookie);
+
+ nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->masked, &xor_mapped_address->unmasked);
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Unmasked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->unmasked.as_string);
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+nr_stun_attr_codec nr_stun_attr_codec_xor_mapped_address = {
+ "xor_mapped_address",
+ nr_stun_attr_codec_xor_mapped_address_print,
+ nr_stun_attr_codec_xor_mapped_address_encode,
+ nr_stun_attr_codec_xor_mapped_address_decode
+};
+
+nr_stun_attr_codec nr_stun_attr_codec_old_xor_mapped_address = {
+ "xor_mapped_address",
+ nr_stun_attr_codec_xor_mapped_address_print,
+ 0, /* never encode this type */
+ nr_stun_attr_codec_xor_mapped_address_decode
+};
+
+nr_stun_attr_codec nr_stun_attr_codec_xor_peer_address = {
+ "xor_peer_address",
+ nr_stun_attr_codec_xor_mapped_address_print,
+ nr_stun_attr_codec_xor_mapped_address_encode,
+ nr_stun_attr_codec_xor_mapped_address_decode
+};
+
+#define NR_ADD_STUN_ATTRIBUTE(type, name, codec, illegal) \
+ { (type), (name), &(codec), illegal },
+
+#define NR_ADD_STUN_ATTRIBUTE_IGNORE(type, name) \
+ { (type), (name), &nr_stun_attr_codec_noop, 0 },
+
+
+static nr_stun_attr_info attrs[] = {
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ALTERNATE_SERVER, "ALTERNATE-SERVER", nr_stun_attr_codec_addr, 0)
+#ifdef USE_STUND_0_96
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_OLD_CHANGE_REQUEST, "CHANGE-REQUEST", nr_stun_attr_codec_UINT4, 0)
+#endif
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ERROR_CODE, "ERROR-CODE", nr_stun_attr_codec_error_code, nr_stun_attr_error_code_illegal)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_FINGERPRINT, "FINGERPRINT", nr_stun_attr_codec_fingerprint, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_MAPPED_ADDRESS, "MAPPED-ADDRESS", nr_stun_attr_codec_addr, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_MESSAGE_INTEGRITY, "MESSAGE-INTEGRITY", nr_stun_attr_codec_message_integrity, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_NONCE, "NONCE", nr_stun_attr_codec_quoted_string, nr_stun_attr_nonce_illegal)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_REALM, "REALM", nr_stun_attr_codec_quoted_string, nr_stun_attr_realm_illegal)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_SERVER, "SERVER", nr_stun_attr_codec_string, nr_stun_attr_server_illegal)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_UNKNOWN_ATTRIBUTES, "UNKNOWN-ATTRIBUTES", nr_stun_attr_codec_unknown_attributes, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_USERNAME, "USERNAME", nr_stun_attr_codec_string, nr_stun_attr_username_illegal)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_MAPPED_ADDRESS, "XOR-MAPPED-ADDRESS", nr_stun_attr_codec_xor_mapped_address, 0)
+
+#ifdef USE_ICE
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ICE_CONTROLLED, "ICE-CONTROLLED", nr_stun_attr_codec_UINT8, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ICE_CONTROLLING, "ICE-CONTROLLING", nr_stun_attr_codec_UINT8, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_PRIORITY, "PRIORITY", nr_stun_attr_codec_UINT4, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_USE_CANDIDATE, "USE-CANDIDATE", nr_stun_attr_codec_flag, 0)
+#endif
+
+#ifdef USE_TURN
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_DATA, "DATA", nr_stun_attr_codec_data, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_LIFETIME, "LIFETIME", nr_stun_attr_codec_UINT4, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_RELAY_ADDRESS, "XOR-RELAY-ADDRESS", nr_stun_attr_codec_xor_mapped_address, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_PEER_ADDRESS, "XOR-PEER-ADDRESS", nr_stun_attr_codec_xor_peer_address, 0)
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_REQUESTED_TRANSPORT, "REQUESTED-TRANSPORT", nr_stun_attr_codec_UCHAR, 0)
+#endif /* USE_TURN */
+
+ /* for backwards compatibilty */
+ NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_OLD_XOR_MAPPED_ADDRESS, "Old XOR-MAPPED-ADDRESS", nr_stun_attr_codec_old_xor_mapped_address, 0)
+#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+ NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_RESPONSE_ADDRESS, "RESPONSE-ADDRESS")
+ NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_SOURCE_ADDRESS, "SOURCE-ADDRESS")
+ NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_CHANGED_ADDRESS, "CHANGED-ADDRESS")
+ NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_PASSWORD, "PASSWORD")
+#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
+};
+
+
+int
+nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info)
+{
+ int _status;
+ int i;
+
+ *info = 0;
+ for (i = 0; i < sizeof(attrs)/sizeof(*attrs); ++i) {
+ if (type == attrs[i].type) {
+ *info = &attrs[i];
+ break;
+ }
+ }
+
+ if (*info == 0)
+ ABORT(R_NOT_FOUND);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_stun_fix_attribute_ordering(nr_stun_message *msg)
+{
+ nr_stun_message_attribute *message_integrity;
+ nr_stun_message_attribute *fingerprint;
+
+ /* 2nd to the last */
+ if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY, &message_integrity)) {
+ TAILQ_REMOVE(&msg->attributes, message_integrity, entry);
+ TAILQ_INSERT_TAIL(&msg->attributes, message_integrity, entry);
+ }
+
+ /* last */
+ if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT, &fingerprint)) {
+ TAILQ_REMOVE(&msg->attributes, fingerprint, entry);
+ TAILQ_INSERT_TAIL(&msg->attributes, fingerprint, entry);
+ }
+
+ return 0;
+}
+
+#ifdef SANITY_CHECKS
+static void sanity_check_encoding_stuff(nr_stun_message *msg)
+{
+ nr_stun_message_attribute *attr = 0;
+ int padding_bytes;
+ int l;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Starting to sanity check encoding");
+
+ l = 0;
+ TAILQ_FOREACH(attr, &msg->attributes, entry) {
+ padding_bytes = 0;
+ if ((attr->length % 4) != 0) {
+ padding_bytes = 4 - (attr->length % 4);
+ }
+ assert(attr->length == (attr->encoding_length - (4 + padding_bytes)));
+ assert(((void*)attr->encoding) == (msg->buffer + 20 + l));
+ l += attr->encoding_length;
+ assert((l % 4) == 0);
+ }
+ assert(l == msg->header.length);
+}
+#endif /* SANITY_CHECKS */
+
+
+int
+nr_stun_encode_message(nr_stun_message *msg)
+{
+ int r,_status;
+ int length_offset;
+ int length_offset_hold;
+ nr_stun_attr_info *attr_info;
+ nr_stun_message_attribute *attr;
+ int padding_bytes;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Encoding STUN message");
+
+ nr_stun_fix_attribute_ordering(msg);
+
+ msg->name = nr_stun_msg_type(msg->header.type);
+ msg->length = 0;
+ msg->header.length = 0;
+
+ if ((r=nr_stun_encode_htons(msg->header.type, sizeof(msg->buffer), msg->buffer, &msg->length)))
+ ABORT(r);
+ if (msg->name)
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Encoded MsgType: %s", msg->name);
+ else
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Encoded MsgType: 0x%03x", msg->header.type);
+
+ /* grab the offset to be used later to re-write the header length field */
+ length_offset_hold = msg->length;
+
+ if ((r=nr_stun_encode_htons(msg->header.length, sizeof(msg->buffer), msg->buffer, &msg->length)))
+ ABORT(r);
+
+ if ((r=nr_stun_encode_htonl(msg->header.magic_cookie, sizeof(msg->buffer), msg->buffer, &msg->length)))
+ ABORT(r);
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Encoded Cookie: %08x", msg->header.magic_cookie);
+
+ if ((r=nr_stun_encode((UCHAR*)(&msg->header.id), sizeof(msg->header.id), sizeof(msg->buffer), msg->buffer, &msg->length)))
+ ABORT(r);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, "Encoded ID", (void*)&msg->header.id, sizeof(msg->header.id));
+
+ TAILQ_FOREACH(attr, &msg->attributes, entry) {
+ if ((r=nr_stun_find_attr_info(attr->type, &attr_info))) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Unrecognized attribute: 0x%04x", attr->type);
+ ABORT(R_INTERNAL);
+ }
+
+ attr->name = attr_info->name;
+ attr->type_name = attr_info->codec->name;
+ attr->encoding = (nr_stun_encoded_attribute*)&msg->buffer[msg->length];
+
+ if (attr_info->codec->encode != 0) {
+ if ((r=attr_info->codec->encode(attr_info, &attr->u, msg->length, sizeof(msg->buffer), msg->buffer, &attr->encoding_length))) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Unable to encode %s", attr_info->name);
+ ABORT(r);
+ }
+
+ msg->length += attr->encoding_length;
+ attr->length = attr->encoding_length - 4; /* -4 for type and length fields */
+
+ if (attr_info->illegal) {
+ if ((r=attr_info->illegal(attr_info, attr->length, &attr->u)))
+ ABORT(r);
+ }
+
+ attr_info->codec->print(attr_info, "Encoded", &attr->u);
+
+ if ((attr->length % 4) == 0) {
+ padding_bytes = 0;
+ }
+ else {
+ padding_bytes = 4 - (attr->length % 4);
+ nr_stun_encode((UCHAR*)"\0\0\0\0", padding_bytes, sizeof(msg->buffer), msg->buffer, &msg->length);
+ attr->encoding_length += padding_bytes;
+ }
+
+ msg->header.length += attr->encoding_length;
+ length_offset = length_offset_hold;
+ (void)nr_stun_encode_htons(msg->header.length, sizeof(msg->buffer), msg->buffer, &length_offset);
+ }
+ else {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing encode function for attribute: %s", attr_info->name);
+ }
+ }
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Encoded Length: %d", msg->header.length);
+
+ assert(msg->length < NR_STUN_MAX_MESSAGE_SIZE);
+
+#ifdef SANITY_CHECKS
+ sanity_check_encoding_stuff(msg);
+#endif /* SANITY_CHECKS */
+
+ _status=0;
+abort:
+ return _status;
+}
+
+int
+nr_stun_decode_message(nr_stun_message *msg, int (*get_password)(void *arg, nr_stun_message *msg, Data **password), void *arg)
+{
+ int r,_status;
+ int offset;
+ int size;
+ int padding_bytes;
+ nr_stun_message_attribute *attr;
+ nr_stun_attr_info *attr_info;
+ Data *password;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Parsing STUN message of %d bytes", msg->length);
+
+ if (!TAILQ_EMPTY(&msg->attributes))
+ ABORT(R_BAD_ARGS);
+
+ if (sizeof(nr_stun_message_header) > msg->length) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Message too small");
+ ABORT(R_FAILED);
+ }
+
+ memcpy(&msg->header, msg->buffer, sizeof(msg->header));
+ msg->header.type = ntohs(msg->header.type);
+ msg->header.length = ntohs(msg->header.length);
+ msg->header.magic_cookie = ntohl(msg->header.magic_cookie);
+
+ msg->name = nr_stun_msg_type(msg->header.type);
+
+ if (msg->name)
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed MsgType: %s", msg->name);
+ else
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed MsgType: 0x%03x", msg->header.type);
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed Length: %d", msg->header.length);
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Parsed Cookie: %08x", msg->header.magic_cookie);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, "Parsed ID", (void*)&msg->header.id, sizeof(msg->header.id));
+
+ if (msg->header.length + sizeof(msg->header) != msg->length) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Inconsistent message header length: %d/%d",
+ msg->header.length, msg->length);
+ ABORT(R_FAILED);
+ }
+
+ size = msg->header.length;
+
+ if ((size % 4) != 0) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal message size: %d", msg->header.length);
+ ABORT(R_FAILED);
+ }
+
+ offset = sizeof(msg->header);
+
+ while (size > 0) {
+ r_log(NR_LOG_STUN, LOG_DEBUG, "size = %d", size);
+
+ if (size < 4) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Illegal message length: %d", size);
+ ABORT(R_FAILED);
+ }
+
+ if ((r=nr_stun_message_attribute_create(msg, &attr)))
+ ABORT(R_NO_MEMORY);
+
+ attr->encoding = (nr_stun_encoded_attribute*)&msg->buffer[offset];
+ attr->type = ntohs(attr->encoding->type);
+ attr->length = ntohs(attr->encoding->length);
+ attr->encoding_length = attr->length + 4;
+
+ if ((attr->length % 4) != 0) {
+ padding_bytes = 4 - (attr->length % 4);
+ attr->encoding_length += padding_bytes;
+ }
+
+ if ((attr->encoding_length) > size) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attribute length larger than remaining message size: %d/%d", attr->encoding_length, size);
+ ABORT(R_FAILED);
+ }
+
+ if ((r=nr_stun_find_attr_info(attr->type, &attr_info))) {
+ if (attr->type <= 0x7FFF)
+ ++msg->comprehension_required_unknown_attributes;
+ else
+ ++msg->comprehension_optional_unknown_attributes;
+ r_log(NR_LOG_STUN, LOG_INFO, "Unrecognized attribute: 0x%04x", attr->type);
+ }
+ else {
+ attr_info->name = attr_info->name;
+ attr->type_name = attr_info->codec->name;
+
+ if (attr->type == NR_STUN_ATTR_MESSAGE_INTEGRITY) {
+ if (get_password && get_password(arg, msg, &password) == 0) {
+ if (password->len > sizeof(attr->u.message_integrity.password)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Password too long: %d bytes", password->len);
+ ABORT(R_FAILED);
+ }
+
+ memcpy(attr->u.message_integrity.password, password->data, password->len);
+ attr->u.message_integrity.passwordlen = password->len;
+ }
+ else {
+ /* set to user "not found" */
+ attr->u.message_integrity.unknown_user = 1;
+ }
+ }
+ else if (attr->type == NR_STUN_ATTR_OLD_XOR_MAPPED_ADDRESS) {
+ attr->type = NR_STUN_ATTR_XOR_MAPPED_ADDRESS;
+ r_log(NR_LOG_STUN, LOG_INFO, "Translating obsolete XOR-MAPPED-ADDRESS type");
+ }
+
+ if ((r=attr_info->codec->decode(attr_info, attr->length, msg->buffer, offset+4, msg->length, &attr->u))) {
+ if (r == SKIP_ATTRIBUTE_DECODE) {
+ r_log(NR_LOG_STUN, LOG_INFO, "Skipping %s", attr_info->name);
+ }
+ else {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Unable to parse %s", attr_info->name);
+ }
+
+ attr->invalid = 1;
+ }
+ else {
+ attr_info->codec->print(attr_info, "Parsed", &attr->u);
+
+#ifdef USE_STUN_PEDANTIC
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Before pedantic attr_info checks");
+ if (attr_info->illegal) {
+ if ((r=attr_info->illegal(attr_info, attr->length, &attr->u))) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Failed pedantic attr_info checks");
+ ABORT(r);
+ }
+ }
+ r_log(NR_LOG_STUN, LOG_DEBUG, "After pedantic attr_info checks");
+#endif /* USE_STUN_PEDANTIC */
+ }
+ }
+
+ offset += attr->encoding_length;
+ size -= attr->encoding_length;
+ }
+
+#ifdef SANITY_CHECKS
+ sanity_check_encoding_stuff(msg);
+#endif /* SANITY_CHECKS */
+
+ _status=0;
+ abort:
+ return _status;
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_codec.h b/media/mtransport/third_party/nICEr/src/stun/stun_codec.h
new file mode 100644
index 000000000..53e64334c
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_codec.h
@@ -0,0 +1,78 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_codec_h
+#define _stun_codec_h
+
+#include "stun_msg.h"
+
+typedef struct nr_stun_attr_info_ nr_stun_attr_info;
+
+typedef struct nr_stun_attr_codec_ {
+ char *name;
+ int (*print)(nr_stun_attr_info *attr_info, char *msg, void *data);
+ int (*encode)(nr_stun_attr_info *attr_info, void *data, int offset, int buflen, UCHAR *buf, int *attrlen);
+ int (*decode)(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
+} nr_stun_attr_codec;
+
+struct nr_stun_attr_info_ {
+ UINT2 type;
+ char *name;
+ nr_stun_attr_codec *codec;
+ int (*illegal)(nr_stun_attr_info *attr_info, int attrlen, void *data);
+};
+
+extern nr_stun_attr_codec nr_stun_attr_codec_UINT4;
+extern nr_stun_attr_codec nr_stun_attr_codec_UINT8;
+extern nr_stun_attr_codec nr_stun_attr_codec_addr;
+extern nr_stun_attr_codec nr_stun_attr_codec_bytes;
+extern nr_stun_attr_codec nr_stun_attr_codec_data;
+extern nr_stun_attr_codec nr_stun_attr_codec_error_code;
+extern nr_stun_attr_codec nr_stun_attr_codec_fingerprint;
+extern nr_stun_attr_codec nr_stun_attr_codec_flag;
+extern nr_stun_attr_codec nr_stun_attr_codec_message_integrity;
+extern nr_stun_attr_codec nr_stun_attr_codec_noop;
+extern nr_stun_attr_codec nr_stun_attr_codec_quoted_string;
+extern nr_stun_attr_codec nr_stun_attr_codec_string;
+extern nr_stun_attr_codec nr_stun_attr_codec_unknown_attributes;
+extern nr_stun_attr_codec nr_stun_attr_codec_xor_mapped_address;
+extern nr_stun_attr_codec nr_stun_attr_codec_xor_peer_address;
+extern nr_stun_attr_codec nr_stun_attr_codec_old_xor_mapped_address;
+
+
+int nr_stun_encode_message(nr_stun_message *msg);
+int nr_stun_decode_message(nr_stun_message *msg, int (*get_password)(void *arg, nr_stun_message *msg, Data **password), void *arg);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_hint.c b/media/mtransport/third_party/nICEr/src/stun/stun_hint.c
new file mode 100644
index 000000000..941b14d64
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_hint.c
@@ -0,0 +1,249 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_hint.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else /* UNIX */
+#include <string.h>
+#endif /* end UNIX */
+#include <assert.h>
+
+#include "stun.h"
+
+
+/* returns 0 if it's not a STUN message
+ * 1 if it's likely to be a STUN message
+ * 2 if it's super likely to be a STUN message
+ * 3 if it really is a STUN message */
+int
+nr_is_stun_message(UCHAR *buf, int len)
+{
+ const UINT4 cookie = htonl(NR_STUN_MAGIC_COOKIE);
+ const UINT4 cookie2 = htonl(NR_STUN_MAGIC_COOKIE2);
+#if 0
+ nr_stun_message msg;
+#endif
+ UINT2 type;
+ nr_stun_encoded_attribute* attr;
+ unsigned int attrLen;
+ int atrType;
+
+ if (sizeof(nr_stun_message_header) > len)
+ return 0;
+
+ if ((buf[0] & (0x80|0x40)) != 0)
+ return 0;
+
+ memcpy(&type, buf, 2);
+ type = ntohs(type);
+
+ switch (type) {
+ case NR_STUN_MSG_BINDING_REQUEST:
+ case NR_STUN_MSG_BINDING_INDICATION:
+ case NR_STUN_MSG_BINDING_RESPONSE:
+ case NR_STUN_MSG_BINDING_ERROR_RESPONSE:
+
+#ifdef USE_TURN
+ case NR_STUN_MSG_ALLOCATE_REQUEST:
+ case NR_STUN_MSG_ALLOCATE_RESPONSE:
+ case NR_STUN_MSG_ALLOCATE_ERROR_RESPONSE:
+ case NR_STUN_MSG_REFRESH_REQUEST:
+ case NR_STUN_MSG_REFRESH_RESPONSE:
+ case NR_STUN_MSG_REFRESH_ERROR_RESPONSE:
+ case NR_STUN_MSG_PERMISSION_REQUEST:
+ case NR_STUN_MSG_PERMISSION_RESPONSE:
+ case NR_STUN_MSG_PERMISSION_ERROR_RESPONSE:
+ case NR_STUN_MSG_CHANNEL_BIND_REQUEST:
+ case NR_STUN_MSG_CHANNEL_BIND_RESPONSE:
+ case NR_STUN_MSG_CHANNEL_BIND_ERROR_RESPONSE:
+ case NR_STUN_MSG_SEND_INDICATION:
+ case NR_STUN_MSG_DATA_INDICATION:
+#ifdef NR_STUN_MSG_CONNECT_REQUEST
+ case NR_STUN_MSG_CONNECT_REQUEST:
+#endif
+#ifdef NR_STUN_MSG_CONNECT_RESPONSE
+ case NR_STUN_MSG_CONNECT_RESPONSE:
+#endif
+#ifdef NR_STUN_MSG_CONNECT_ERROR_RESPONSE
+ case NR_STUN_MSG_CONNECT_ERROR_RESPONSE:
+#endif
+#ifdef NR_STUN_MSG_CONNECT_STATUS_INDICATION
+ case NR_STUN_MSG_CONNECT_STATUS_INDICATION:
+#endif
+#endif /* USE_TURN */
+
+ /* ok so far, continue */
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ if (!memcmp(&cookie2, &buf[4], sizeof(UINT4))) {
+ /* return here because if it's an old-style message then there will
+ * not be a fingerprint in the message */
+ return 1;
+ }
+
+ if (memcmp(&cookie, &buf[4], sizeof(UINT4)))
+ return 0;
+
+ /* the magic cookie was right, so it's pretty darn likely that what we've
+ * got here is a STUN message */
+
+ attr = (nr_stun_encoded_attribute*)(buf + (len - 8));
+ attrLen = ntohs(attr->length);
+ atrType = ntohs(attr->type);
+
+ if (atrType != NR_STUN_ATTR_FINGERPRINT || attrLen != 4)
+ return 1;
+
+ /* the fingerprint is in the right place and looks sane, so we can be quite
+ * sure we've got a STUN message */
+
+#if 0
+/* nevermind this check ... there's a reasonable chance that a NAT has modified
+ * the message (and thus the fingerprint check will fail), but it's still an
+ * otherwise-perfectly-good STUN message, so skip the check since we're going
+ * to return "true" whether the check succeeds or fails */
+
+ if (nr_stun_parse_attr_UINT4(buf + (len - 4), attrLen, &msg.fingerprint))
+ return 2;
+
+
+ if (nr_stun_compute_fingerprint(buf, len - 8, &computedFingerprint))
+ return 2;
+
+ if (msg.fingerprint.number != computedFingerprint)
+ return 2;
+
+ /* and the fingerprint is good, so it's gotta be a STUN message */
+#endif
+
+ return 3;
+}
+
+int
+nr_is_stun_request_message(UCHAR *buf, int len)
+{
+ UINT2 type;
+
+ if (sizeof(nr_stun_message_header) > len)
+ return 0;
+
+ if (!nr_is_stun_message(buf, len))
+ return 0;
+
+ memcpy(&type, buf, 2);
+ type = ntohs(type);
+
+ return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_REQUEST;
+}
+
+int
+nr_is_stun_indication_message(UCHAR *buf, int len)
+{
+ UINT2 type;
+
+ if (sizeof(nr_stun_message_header) > len)
+ return 0;
+
+ if (!nr_is_stun_message(buf, len))
+ return 0;
+
+ memcpy(&type, buf, 2);
+ type = ntohs(type);
+
+ return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_INDICATION;
+}
+
+int
+nr_is_stun_response_message(UCHAR *buf, int len)
+{
+ UINT2 type;
+
+ if (sizeof(nr_stun_message_header) > len)
+ return 0;
+
+ if (!nr_is_stun_message(buf, len))
+ return 0;
+
+ memcpy(&type, buf, 2);
+ type = ntohs(type);
+
+ return NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_RESPONSE
+ || NR_STUN_GET_TYPE_CLASS(type) == NR_CLASS_ERROR_RESPONSE;
+}
+
+int
+nr_has_stun_cookie(UCHAR *buf, int len)
+{
+ static UINT4 cookie;
+
+ cookie = htonl(NR_STUN_MAGIC_COOKIE);
+
+ if (sizeof(nr_stun_message_header) > len)
+ return 0;
+
+ if (memcmp(&cookie, &buf[4], sizeof(UINT4)))
+ return 0;
+
+ return 1;
+}
+
+int
+nr_stun_message_length(UCHAR *buf, int buf_len, int *msg_len)
+{
+ nr_stun_message_header *hdr;
+
+ if (!nr_is_stun_message(buf, buf_len))
+ return(R_BAD_DATA);
+
+ hdr = (nr_stun_message_header *)buf;
+
+ *msg_len = ntohs(hdr->length);
+
+ return(0);
+}
+
+
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_hint.h b/media/mtransport/third_party/nICEr/src/stun/stun_hint.h
new file mode 100644
index 000000000..4b285d31d
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_hint.h
@@ -0,0 +1,44 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _stun_hint_h
+#define _stun_hint_h
+
+int nr_is_stun_message(UCHAR *buf, int len);
+int nr_is_stun_request_message(UCHAR *buf, int len);
+int nr_is_stun_response_message(UCHAR *buf, int len);
+int nr_is_stun_indication_message(UCHAR *buf, int len);
+int nr_has_stun_cookie(UCHAR *buf, int len);
+int nr_stun_message_length(UCHAR *buf, int len, int *length);
+
+#endif
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_msg.c b/media/mtransport/third_party/nICEr/src/stun/stun_msg.c
new file mode 100644
index 000000000..c34bb46b0
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_msg.c
@@ -0,0 +1,360 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_msg.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else /* UNIX */
+#include <string.h>
+#endif /* end UNIX */
+#include <assert.h>
+
+#include "stun.h"
+
+
+int
+nr_stun_message_create(nr_stun_message **msg)
+{
+ int _status;
+ nr_stun_message *m = 0;
+
+ m = RCALLOC(sizeof(*m));
+ if (!m)
+ ABORT(R_NO_MEMORY);
+
+ TAILQ_INIT(&m->attributes);
+
+ *msg = m;
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_stun_message_create2(nr_stun_message **msg, UCHAR *buffer, int length)
+{
+ int r,_status;
+ nr_stun_message *m = 0;
+
+ if (length > sizeof(m->buffer)) {
+ ABORT(R_BAD_DATA);
+ }
+
+ if ((r=nr_stun_message_create(&m)))
+ ABORT(r);
+
+ memcpy(m->buffer, buffer, length);
+ m->length = length;
+
+ *msg = m;
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_stun_message_destroy(nr_stun_message **msg)
+{
+ int _status;
+ nr_stun_message_attribute_head *attrs;
+ nr_stun_message_attribute *attr;
+
+ if (msg && *msg) {
+ attrs = &(*msg)->attributes;
+ while (!TAILQ_EMPTY(attrs)) {
+ attr = TAILQ_FIRST(attrs);
+ nr_stun_message_attribute_destroy(*msg, &attr);
+ }
+
+ RFREE(*msg);
+
+ *msg = 0;
+ }
+
+ _status=0;
+/* abort: */
+ return(_status);
+}
+
+int
+nr_stun_message_attribute_create(nr_stun_message *msg, nr_stun_message_attribute **attr)
+{
+ int _status;
+ nr_stun_message_attribute *a = 0;
+
+ a = RCALLOC(sizeof(*a));
+ if (!a)
+ ABORT(R_NO_MEMORY);
+
+ TAILQ_INSERT_TAIL(&msg->attributes, a, entry);
+
+ *attr = a;
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_stun_message_attribute_destroy(nr_stun_message *msg, nr_stun_message_attribute **attr)
+{
+ int _status;
+ nr_stun_message_attribute *a = 0;
+
+ if (attr && *attr) {
+ a = *attr;
+ TAILQ_REMOVE(&msg->attributes, a, entry);
+
+ RFREE(a);
+
+ *attr = 0;
+ }
+
+ _status=0;
+/* abort: */
+ return(_status);
+}
+
+int
+nr_stun_message_has_attribute(nr_stun_message *msg, UINT2 type, nr_stun_message_attribute **attribute)
+{
+ nr_stun_message_attribute *attr = 0;
+
+ if (attribute)
+ *attribute = 0;
+
+ TAILQ_FOREACH(attr, &msg->attributes, entry) {
+ if (attr->type == type)
+ break;
+ }
+
+ if (!attr || attr->invalid)
+ return 0; /* does not have */
+
+ if (attribute)
+ *attribute = attr;
+
+ return 1; /* has */
+}
+
+#define NR_STUN_MESSAGE_ADD_ATTRIBUTE(__type, __code) \
+ { \
+ int r,_status; \
+ nr_stun_message_attribute *attr = 0; \
+ if ((r=nr_stun_message_attribute_create(msg, &attr))) \
+ ABORT(r); \
+ attr->type = (__type); \
+ { __code } \
+ _status=0; \
+ abort: \
+ if (_status){ \
+ nr_stun_message_attribute_destroy(msg, &attr); \
+ } \
+ return(_status); \
+ }
+
+
+int
+nr_stun_message_add_alternate_server_attribute(nr_stun_message *msg, nr_transport_addr *alternate_server)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_ALTERNATE_SERVER,
+ {
+ if ((r=nr_transport_addr_copy(&attr->u.alternate_server, alternate_server)))
+ ABORT(r);
+ }
+)
+
+int
+nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, char *reason)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_ERROR_CODE,
+ {
+ attr->u.error_code.number = number;
+ strlcpy(attr->u.error_code.reason, reason, sizeof(attr->u.error_code.reason));
+ }
+)
+
+int
+nr_stun_message_add_fingerprint_attribute(nr_stun_message *msg)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_FINGERPRINT,
+ {}
+)
+
+int
+nr_stun_message_add_message_integrity_attribute(nr_stun_message *msg, Data *password)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_MESSAGE_INTEGRITY,
+ {
+ if (sizeof(attr->u.message_integrity.password) < password->len)
+ ABORT(R_BAD_DATA);
+
+ memcpy(attr->u.message_integrity.password, password->data, password->len);
+ attr->u.message_integrity.passwordlen = password->len;
+ }
+)
+
+int
+nr_stun_message_add_nonce_attribute(nr_stun_message *msg, char *nonce)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_NONCE,
+ { strlcpy(attr->u.nonce, nonce, sizeof(attr->u.nonce)); }
+)
+
+int
+nr_stun_message_add_realm_attribute(nr_stun_message *msg, char *realm)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_REALM,
+ { strlcpy(attr->u.realm, realm, sizeof(attr->u.realm)); }
+)
+
+int
+nr_stun_message_add_server_attribute(nr_stun_message *msg, char *server_name)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_SERVER,
+ { strlcpy(attr->u.server_name, server_name, sizeof(attr->u.server_name)); }
+)
+
+int
+nr_stun_message_add_unknown_attributes_attribute(nr_stun_message *msg, nr_stun_attr_unknown_attributes *unknown_attributes)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_UNKNOWN_ATTRIBUTES,
+ { memcpy(&attr->u.unknown_attributes, unknown_attributes, sizeof(attr->u.unknown_attributes)); }
+)
+
+int
+nr_stun_message_add_username_attribute(nr_stun_message *msg, char *username)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_USERNAME,
+ { strlcpy(attr->u.username, username, sizeof(attr->u.username)); }
+)
+
+int
+nr_stun_message_add_requested_transport_attribute(nr_stun_message *msg, UCHAR protocol)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_REQUESTED_TRANSPORT,
+ { attr->u.requested_transport = protocol; }
+)
+
+int
+nr_stun_message_add_xor_mapped_address_attribute(nr_stun_message *msg, nr_transport_addr *mapped_address)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_XOR_MAPPED_ADDRESS,
+ {
+ if ((r=nr_transport_addr_copy(&attr->u.xor_mapped_address.unmasked, mapped_address)))
+ ABORT(r);
+ }
+)
+
+int
+nr_stun_message_add_xor_peer_address_attribute(nr_stun_message *msg, nr_transport_addr *peer_address)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_XOR_PEER_ADDRESS,
+ {
+ if ((r=nr_transport_addr_copy(&attr->u.xor_mapped_address.unmasked, peer_address)))
+ ABORT(r);
+ }
+)
+
+#ifdef USE_ICE
+int
+nr_stun_message_add_ice_controlled_attribute(nr_stun_message *msg, UINT8 ice_controlled)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_ICE_CONTROLLED,
+ { attr->u.ice_controlled = ice_controlled; }
+)
+
+int
+nr_stun_message_add_ice_controlling_attribute(nr_stun_message *msg, UINT8 ice_controlling)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_ICE_CONTROLLING,
+ { attr->u.ice_controlling = ice_controlling; }
+)
+
+int
+nr_stun_message_add_priority_attribute(nr_stun_message *msg, UINT4 priority)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_PRIORITY,
+ { attr->u.priority = priority; }
+)
+
+int
+nr_stun_message_add_use_candidate_attribute(nr_stun_message *msg)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_USE_CANDIDATE,
+ {}
+)
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+int
+nr_stun_message_add_data_attribute(nr_stun_message *msg, UCHAR *data, int length)
+
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_DATA,
+ {
+ if (length > NR_STUN_MAX_MESSAGE_SIZE)
+ ABORT(R_BAD_ARGS);
+
+ memcpy(attr->u.data.data, data, length);
+ attr->u.data.length=length;
+ }
+)
+
+int
+nr_stun_message_add_lifetime_attribute(nr_stun_message *msg, UINT4 lifetime_secs)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_LIFETIME,
+ { attr->u.lifetime_secs = lifetime_secs; }
+)
+
+#endif /* USE_TURN */
+
+#ifdef USE_STUND_0_96
+int
+nr_stun_message_add_change_request_attribute(nr_stun_message *msg, UINT4 change_request)
+NR_STUN_MESSAGE_ADD_ATTRIBUTE(
+ NR_STUN_ATTR_OLD_CHANGE_REQUEST,
+ { attr->u.change_request = change_request; }
+)
+#endif /* USE_STUND_0_96 */
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_msg.h b/media/mtransport/third_party/nICEr/src/stun/stun_msg.h
new file mode 100644
index 000000000..927ce2e3c
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_msg.h
@@ -0,0 +1,206 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_msg_h
+#define _stun_msg_h
+
+#include "csi_platform.h"
+#include "nr_api.h"
+#include "transport_addr.h"
+
+#define NR_STUN_MAX_USERNAME_BYTES 513
+#define NR_STUN_MAX_ERROR_CODE_REASON_BYTES 763
+#define NR_STUN_MAX_ERROR_CODE_REASON_CHARS 128
+#define NR_STUN_MAX_REALM_BYTES 763
+#define NR_STUN_MAX_REALM_CHARS 128
+#define NR_STUN_MAX_NONCE_BYTES 763
+#define NR_STUN_MAX_NONCE_CHARS 128
+#define NR_STUN_MAX_SERVER_BYTES 763
+#define NR_STUN_MAX_SERVER_CHARS 128
+#define NR_STUN_MAX_STRING_SIZE 763 /* any possible string */
+#define NR_STUN_MAX_UNKNOWN_ATTRIBUTES 16
+#define NR_STUN_MAX_MESSAGE_SIZE 2048
+
+#define NR_STUN_MAGIC_COOKIE 0x2112A442
+#define NR_STUN_MAGIC_COOKIE2 0xc5cb4e1d /* used recognize old stun messages */
+
+typedef struct { UCHAR octet[12]; } UINT12;
+
+typedef struct nr_stun_attr_error_code_ {
+ UINT2 number;
+ char reason[NR_STUN_MAX_ERROR_CODE_REASON_BYTES+1]; /* +1 for \0 */
+} nr_stun_attr_error_code;
+
+typedef struct nr_stun_attr_fingerprint_ {
+ UINT4 checksum;
+ int valid;
+} nr_stun_attr_fingerprint;
+
+typedef struct nr_stun_attr_message_integrity_ {
+ UCHAR hash[20];
+ int unknown_user;
+ UCHAR password[1024];
+ int passwordlen;
+ int valid;
+} nr_stun_attr_message_integrity;
+
+typedef struct nr_stun_attr_unknown_attributes_ {
+ UINT2 attribute[NR_STUN_MAX_UNKNOWN_ATTRIBUTES];
+ int num_attributes;
+} nr_stun_attr_unknown_attributes;
+
+typedef struct nr_stun_attr_xor_mapped_address_ {
+ nr_transport_addr masked;
+ nr_transport_addr unmasked;
+} nr_stun_attr_xor_mapped_address;
+
+typedef struct nr_stun_attr_data_ {
+ UCHAR data[NR_STUN_MAX_MESSAGE_SIZE];
+ int length;
+} nr_stun_attr_data;
+
+
+typedef struct nr_stun_encoded_attribute_ {
+ UINT2 type;
+ UINT2 length;
+ UCHAR value[NR_STUN_MAX_MESSAGE_SIZE];
+} nr_stun_encoded_attribute;
+
+typedef struct nr_stun_message_attribute_ {
+ UINT2 type;
+ UINT2 length;
+ union {
+ nr_transport_addr address;
+ nr_transport_addr alternate_server;
+ nr_stun_attr_error_code error_code;
+ nr_stun_attr_fingerprint fingerprint;
+ nr_transport_addr mapped_address;
+ nr_stun_attr_message_integrity message_integrity;
+ char nonce[NR_STUN_MAX_NONCE_BYTES+1]; /* +1 for \0 */
+ char realm[NR_STUN_MAX_REALM_BYTES+1]; /* +1 for \0 */
+ nr_stun_attr_xor_mapped_address relay_address;
+ char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
+ nr_stun_attr_unknown_attributes unknown_attributes;
+ char username[NR_STUN_MAX_USERNAME_BYTES+1]; /* +1 for \0 */
+ nr_stun_attr_xor_mapped_address xor_mapped_address;
+
+#ifdef USE_ICE
+ UINT4 priority;
+ UINT8 ice_controlled;
+ UINT8 ice_controlling;
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+ UINT4 lifetime_secs;
+ nr_transport_addr remote_address;
+ UCHAR requested_transport;
+ nr_stun_attr_data data;
+#endif /* USE_TURN */
+
+#ifdef USE_STUND_0_96
+ UINT4 change_request;
+#endif /* USE_STUND_0_96 */
+
+ /* make sure there's enough room here to place any possible
+ * attribute */
+ UCHAR largest_possible_attribute[NR_STUN_MAX_MESSAGE_SIZE];
+ } u;
+ nr_stun_encoded_attribute *encoding;
+ int encoding_length;
+ char *name;
+ char *type_name;
+ int invalid;
+ TAILQ_ENTRY(nr_stun_message_attribute_) entry;
+} nr_stun_message_attribute;
+
+typedef TAILQ_HEAD(nr_stun_message_attribute_head_,nr_stun_message_attribute_) nr_stun_message_attribute_head;
+
+typedef struct nr_stun_message_header_ {
+ UINT2 type;
+ UINT2 length;
+ UINT4 magic_cookie;
+ UINT12 id;
+} nr_stun_message_header;
+
+typedef struct nr_stun_message_ {
+ char *name;
+ UCHAR buffer[NR_STUN_MAX_MESSAGE_SIZE];
+ int length;
+ nr_stun_message_header header;
+ int comprehension_required_unknown_attributes;
+ int comprehension_optional_unknown_attributes;
+ nr_stun_message_attribute_head attributes;
+} nr_stun_message;
+
+int nr_stun_message_create(nr_stun_message **msg);
+int nr_stun_message_create2(nr_stun_message **msg, UCHAR *buffer, int length);
+int nr_stun_message_destroy(nr_stun_message **msg);
+
+int nr_stun_message_attribute_create(nr_stun_message *msg, nr_stun_message_attribute **attr);
+int nr_stun_message_attribute_destroy(nr_stun_message *msg, nr_stun_message_attribute **attr);
+
+int nr_stun_message_has_attribute(nr_stun_message *msg, UINT2 type, nr_stun_message_attribute **attribute);
+
+int nr_stun_message_add_alternate_server_attribute(nr_stun_message *msg, nr_transport_addr *alternate_server);
+int nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, char *reason);
+int nr_stun_message_add_fingerprint_attribute(nr_stun_message *msg);
+int nr_stun_message_add_message_integrity_attribute(nr_stun_message *msg, Data *password);
+int nr_stun_message_add_nonce_attribute(nr_stun_message *msg, char *nonce);
+int nr_stun_message_add_realm_attribute(nr_stun_message *msg, char *realm);
+int nr_stun_message_add_server_attribute(nr_stun_message *msg, char *server_name);
+int nr_stun_message_add_unknown_attributes_attribute(nr_stun_message *msg, nr_stun_attr_unknown_attributes *unknown_attributes);
+int nr_stun_message_add_username_attribute(nr_stun_message *msg, char *username);
+int nr_stun_message_add_xor_mapped_address_attribute(nr_stun_message *msg, nr_transport_addr *mapped_address);
+
+#ifdef USE_ICE
+int nr_stun_message_add_ice_controlled_attribute(nr_stun_message *msg, UINT8 ice_controlled);
+int nr_stun_message_add_ice_controlling_attribute(nr_stun_message *msg, UINT8 ice_controlling);
+int nr_stun_message_add_priority_attribute(nr_stun_message *msg, UINT4 priority);
+int nr_stun_message_add_use_candidate_attribute(nr_stun_message *msg);
+#endif /* USE_ICE */
+
+#ifdef USE_TURN
+int nr_stun_message_add_data_attribute(nr_stun_message *msg, UCHAR *data, int length);
+int nr_stun_message_add_lifetime_attribute(nr_stun_message *msg, UINT4 lifetime_secs);
+int nr_stun_message_add_requested_transport_attribute(nr_stun_message *msg, UCHAR transport);
+int
+nr_stun_message_add_xor_peer_address_attribute(nr_stun_message *msg, nr_transport_addr *peer_address);
+#endif /* USE_TURN */
+
+#ifdef USE_STUND_0_96
+int nr_stun_message_add_change_request_attribute(nr_stun_message *msg, UINT4 change_request);
+#endif /* USE_STUND_0_96 */
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_proc.c b/media/mtransport/third_party/nICEr/src/stun/stun_proc.c
new file mode 100644
index 000000000..336100264
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_proc.c
@@ -0,0 +1,568 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_proc.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else /* UNIX */
+#include <string.h>
+#endif /* end UNIX */
+#include <assert.h>
+
+#include "stun.h"
+#include "stun_reg.h"
+#include "registry.h"
+
+static int
+nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
+int
+nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
+{
+ int _status;
+ nr_stun_message_attribute *attr;
+
+#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+ /* if this message was generated by an RFC 3489 impementation,
+ * the call to nr_is_stun_message will fail, so skip that
+ * check and puke elsewhere if the message can't be decoded */
+ if (msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE
+ || msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE2) {
+#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
+ if (!nr_is_stun_message(msg->buffer, msg->length)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Not a STUN message");
+ ABORT(R_REJECTED);
+ }
+#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+ }
+#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
+
+ if (req == 0) {
+ if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_REQUEST) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message type: %03x", msg->header.type);
+ ABORT(R_REJECTED);
+ }
+ }
+ else {
+ if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_RESPONSE
+ && NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_ERROR_RESPONSE) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message class: %03x", msg->header.type);
+ ABORT(R_REJECTED);
+ }
+
+ if (NR_STUN_GET_TYPE_METHOD(req->header.type) != NR_STUN_GET_TYPE_METHOD(msg->header.type)) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"Inconsistent message method: %03x expected %03x", msg->header.type, req->header.type);
+ ABORT(R_REJECTED);
+ }
+
+ if (nr_stun_different_transaction(msg->buffer, msg->length, req)) {
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized STUN transaction");
+ ABORT(R_REJECTED);
+ }
+ }
+
+ switch (msg->header.magic_cookie) {
+ case NR_STUN_MAGIC_COOKIE:
+ /* basically draft-ietf-behave-rfc3489bis-10.txt S 6 rules */
+
+ if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT, &attr)
+ && !attr->u.fingerprint.valid) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Invalid fingerprint");
+ ABORT(R_REJECTED);
+ }
+
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MAGIC_COOKIE2:
+ /* nothing to check in this case */
+ break;
+#endif /* USE_STUND_0_96 */
+
+ default:
+#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+ /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
+#else
+#ifdef NDEBUG
+ /* in deployment builds we should always see a recognized magic cookie */
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing Magic Cookie");
+ ABORT(R_REJECTED);
+#else
+ /* ignore this condition because sometimes we like to pretend we're
+ * a server talking to old clients and their messages don't contain
+ * a magic cookie at all but rather the magic cookie field is part
+ * of their ID and therefore random */
+#endif /* NDEBUG */
+#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
+ break;
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1 */
+int
+nr_stun_process_request(nr_stun_message *req, nr_stun_message *res)
+{
+ int _status;
+#ifdef USE_STUN_PEDANTIC
+ int r;
+ nr_stun_attr_unknown_attributes unknown_attributes = { { 0 } };
+ nr_stun_message_attribute *attr;
+
+ if (req->comprehension_required_unknown_attributes > 0) {
+ nr_stun_form_error_response(req, res, 420, "Unknown Attributes");
+
+ TAILQ_FOREACH(attr, &req->attributes, entry) {
+ if (attr->name == 0) {
+ /* unrecognized attribute */
+
+ /* should never happen, but truncate if it ever were to occur */
+ if (unknown_attributes.num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES)
+ break;
+
+ unknown_attributes.attribute[unknown_attributes.num_attributes++] = attr->type;
+ }
+ }
+
+ assert(req->comprehension_required_unknown_attributes + req->comprehension_optional_unknown_attributes == unknown_attributes.num_attributes);
+
+ if ((r=nr_stun_message_add_unknown_attributes_attribute(res, &unknown_attributes)))
+ ABORT(R_ALREADY);
+
+ ABORT(R_ALREADY);
+ }
+#endif /* USE_STUN_PEDANTIC */
+
+ _status=0;
+#ifdef USE_STUN_PEDANTIC
+ abort:
+#endif /* USE_STUN_PEDANTIC */
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.2 */
+int
+nr_stun_process_indication(nr_stun_message *ind)
+{
+ int _status;
+#ifdef USE_STUN_PEDANTIC
+
+ if (ind->comprehension_required_unknown_attributes > 0)
+ ABORT(R_REJECTED);
+#endif /* USE_STUN_PEDANTIC */
+
+ _status=0;
+#ifdef USE_STUN_PEDANTIC
+ abort:
+#endif /* USE_STUN_PEDANTIC */
+ return _status;
+}
+
+/* RFC5389 S 7.3.3, except that we *also* allow a MAPPED_ADDRESS
+ to compensate for a bug in Google's STUN server where it
+ always returns MAPPED_ADDRESS.
+
+ Mozilla bug: 888274.
+ */
+int
+nr_stun_process_success_response(nr_stun_message *res)
+{
+ int _status;
+
+#ifdef USE_STUN_PEDANTIC
+ if (res->comprehension_required_unknown_attributes > 0)
+ ABORT(R_REJECTED);
+#endif /* USE_STUN_PEDANTIC */
+
+ if (NR_STUN_GET_TYPE_METHOD(res->header.type) == NR_METHOD_BINDING) {
+ if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0) &&
+ ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_MAPPED_ADDRESS, 0)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing XOR-MAPPED-ADDRESS and MAPPED_ADDRESS");
+ ABORT(R_REJECTED);
+ }
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.4 */
+int
+nr_stun_process_error_response(nr_stun_message *res, UINT2 *error_code)
+{
+ int _status;
+ nr_stun_message_attribute *attr;
+
+ if (res->comprehension_required_unknown_attributes > 0) {
+ ABORT(R_REJECTED);
+ }
+
+ if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, &attr)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing ERROR-CODE");
+ ABORT(R_REJECTED);
+ }
+
+ *error_code = attr->u.error_code.number;
+
+ switch (attr->u.error_code.number / 100) {
+ case 3:
+ /* If the error code is 300 through 399, the client SHOULD consider
+ * the transaction as failed unless the ALTERNATE-SERVER extension is
+ * being used. See Section 11. */
+
+ if (attr->u.error_code.number == 300) {
+ if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ALTERNATE_SERVER, 0)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing ALTERNATE-SERVER");
+ ABORT(R_REJECTED);
+ }
+
+ /* draft-ietf-behave-rfc3489bis-10.txt S 11 */
+ if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
+ ABORT(R_REJECTED);
+ }
+
+ ABORT(R_RETRY);
+ }
+
+ ABORT(R_REJECTED);
+ break;
+
+ case 4:
+ /* If the error code is 400 through 499, the client declares the
+ * transaction failed; in the case of 420 (Unknown Attribute), the
+ * response should contain a UNKNOWN-ATTRIBUTES attribute that gives
+ * additional information. */
+ if (attr->u.error_code.number == 420)
+ ABORT(R_REJECTED);
+
+ /* it may be possible to restart given the info that was received in
+ * this response, so retry */
+ ABORT(R_RETRY);
+ break;
+
+ case 5:
+ /* If the error code is 500 through 599, the client MAY resend the
+ * request; clients that do so MUST limit the number of times they do
+ * this. */
+ /* let the retransmit mechanism handle resending the request */
+ break;
+
+ default:
+ ABORT(R_REJECTED);
+ break;
+ }
+
+ /* the spec says: "The client then does any processing specified by the authentication
+ * mechanism (see Section 10). This may result in a new transaction
+ * attempt." -- but this is handled already elsewhere, so needn't be repeated
+ * in this function */
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.2 */
+int
+nr_stun_receive_request_or_indication_short_term_auth(nr_stun_message *msg,
+ nr_stun_message *res)
+{
+ int _status;
+ nr_stun_message_attribute *attr;
+
+ switch (msg->header.magic_cookie) {
+ default:
+ /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
+ /* drop thru */
+ case NR_STUN_MAGIC_COOKIE:
+ if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
+ nr_stun_form_error_response(msg, res, 400, "Missing MESSAGE-INTEGRITY");
+ ABORT(R_ALREADY);
+ }
+
+ if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, 0)) {
+ nr_stun_form_error_response(msg, res, 400, "Missing USERNAME");
+ ABORT(R_ALREADY);
+ }
+
+ if (attr->u.message_integrity.unknown_user) {
+ nr_stun_form_error_response(msg, res, 401, "Unrecognized USERNAME");
+ ABORT(R_ALREADY);
+ }
+
+ if (!attr->u.message_integrity.valid) {
+ nr_stun_form_error_response(msg, res, 401, "Bad MESSAGE-INTEGRITY");
+ ABORT(R_ALREADY);
+ }
+
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MAGIC_COOKIE2:
+ /* nothing to check in this case */
+ break;
+#endif /* USE_STUND_0_96 */
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.3 */
+int
+nr_stun_receive_response_short_term_auth(nr_stun_message *res)
+{
+ int _status;
+ nr_stun_message_attribute *attr;
+
+ switch (res->header.magic_cookie) {
+ default:
+ /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
+ /* drop thru */
+ case NR_STUN_MAGIC_COOKIE:
+ if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
+ ABORT(R_REJECTED);
+ }
+
+ if (!attr->u.message_integrity.valid) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
+ ABORT(R_REJECTED);
+ }
+
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MAGIC_COOKIE2:
+ /* nothing to check in this case */
+ break;
+#endif /* USE_STUND_0_96 */
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+static int
+nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
+{
+ int r,_status;
+ char *realm = 0;
+ char *nonce;
+ UINT2 size;
+
+ if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_add_realm_attribute(res, realm)))
+ ABORT(r);
+
+ if (clnt) {
+ if (strlen(clnt->nonce) < 1)
+ new_nonce = 1;
+
+ if (new_nonce) {
+ if (NR_reg_get_uint2(NR_STUN_REG_PREF_SERVER_NONCE_SIZE, &size))
+ size = 48;
+
+ if (size > (sizeof(clnt->nonce) - 1))
+ size = sizeof(clnt->nonce) - 1;
+
+ nr_random_alphanum(clnt->nonce, size);
+ clnt->nonce[size] = '\0';
+ }
+
+ nonce = clnt->nonce;
+ }
+ else {
+ /* user is not known, so use a bogus nonce since there's no way to
+ * store a good nonce with the client-specific data -- this nonce
+ * will be recognized as stale if the client attempts another
+ * request */
+ nonce = "STALE";
+ }
+
+ if ((r=nr_stun_message_add_nonce_attribute(res, nonce)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+#ifdef USE_TURN
+assert(_status == 0); /* TODO: !nn! cleanup after I reimplmement TURN */
+#endif
+ RFREE(realm);
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 10.2.1 - 10.2.2 */
+int
+nr_stun_receive_request_long_term_auth(nr_stun_message *req, nr_stun_server_ctx *ctx, nr_stun_message *res)
+{
+ int r,_status;
+ nr_stun_message_attribute *mi;
+ nr_stun_message_attribute *n;
+ nr_stun_server_client *clnt = 0;
+
+ switch (req->header.magic_cookie) {
+ default:
+ /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
+ /* drop thru */
+ case NR_STUN_MAGIC_COOKIE:
+ if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)) {
+ nr_stun_form_error_response(req, res, 400, "Missing USERNAME");
+ nr_stun_add_realm_and_nonce(0, 0, res);
+ ABORT(R_ALREADY);
+ }
+
+ if ((r=nr_stun_get_message_client(ctx, req, &clnt))) {
+ nr_stun_form_error_response(req, res, 401, "Unrecognized USERNAME");
+ nr_stun_add_realm_and_nonce(0, 0, res);
+ ABORT(R_ALREADY);
+ }
+
+ if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, &mi)) {
+ nr_stun_form_error_response(req, res, 401, "Missing MESSAGE-INTEGRITY");
+ nr_stun_add_realm_and_nonce(0, clnt, res);
+ ABORT(R_ALREADY);
+ }
+
+ assert(!mi->u.message_integrity.unknown_user);
+
+ if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_REALM, 0)) {
+ nr_stun_form_error_response(req, res, 400, "Missing REALM");
+ ABORT(R_ALREADY);
+ }
+
+ if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_NONCE, &n)) {
+ nr_stun_form_error_response(req, res, 400, "Missing NONCE");
+ ABORT(R_ALREADY);
+ }
+
+ assert(sizeof(clnt->nonce) == sizeof(n->u.nonce));
+ if (strncmp(clnt->nonce, n->u.nonce, sizeof(n->u.nonce))) {
+ nr_stun_form_error_response(req, res, 438, "Stale NONCE");
+ nr_stun_add_realm_and_nonce(1, clnt, res);
+ ABORT(R_ALREADY);
+ }
+
+ if (!mi->u.message_integrity.valid) {
+ nr_stun_form_error_response(req, res, 401, "Bad MESSAGE-INTEGRITY");
+ nr_stun_add_realm_and_nonce(0, clnt, res);
+ ABORT(R_ALREADY);
+ }
+
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MAGIC_COOKIE2:
+ /* nothing to do in this case */
+ break;
+#endif /* USE_STUND_0_96 */
+ }
+
+ _status=0;
+ abort:
+
+ return _status;
+}
+
+/* draft-ietf-behave-rfc3489bis-10.txt S 10.2.3 */
+int
+nr_stun_receive_response_long_term_auth(nr_stun_message *res, nr_stun_client_ctx *ctx)
+{
+ int _status;
+ nr_stun_message_attribute *attr;
+
+ switch (res->header.magic_cookie) {
+ default:
+ /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
+ /* drop thru */
+ case NR_STUN_MAGIC_COOKIE:
+ if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_REALM, &attr)) {
+ RFREE(ctx->realm);
+ ctx->realm = r_strdup(attr->u.realm);
+ if (!ctx->realm)
+ ABORT(R_NO_MEMORY);
+ }
+ else {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing REALM");
+ ABORT(R_REJECTED);
+ }
+
+ if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_NONCE, &attr)) {
+ RFREE(ctx->nonce);
+ ctx->nonce = r_strdup(attr->u.nonce);
+ if (!ctx->nonce)
+ ABORT(R_NO_MEMORY);
+ }
+ else {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Missing NONCE");
+ ABORT(R_REJECTED);
+ }
+
+ if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
+ if (!attr->u.message_integrity.valid) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
+ ABORT(R_REJECTED);
+ }
+ }
+
+ break;
+
+#ifdef USE_STUND_0_96
+ case NR_STUN_MAGIC_COOKIE2:
+ /* nothing to check in this case */
+ break;
+#endif /* USE_STUND_0_96 */
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_proc.h b/media/mtransport/third_party/nICEr/src/stun/stun_proc.h
new file mode 100644
index 000000000..597567077
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_proc.h
@@ -0,0 +1,53 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_proc_h
+#define _stun_proc_h
+
+#include "stun.h"
+
+int nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg);
+int nr_stun_process_request(nr_stun_message *req, nr_stun_message *res);
+int nr_stun_process_indication(nr_stun_message *ind);
+int nr_stun_process_success_response(nr_stun_message *res);
+int nr_stun_process_error_response(nr_stun_message *res, UINT2 *error_code);
+
+int nr_stun_receive_request_or_indication_short_term_auth(nr_stun_message *msg, nr_stun_message *res);
+int nr_stun_receive_response_short_term_auth(nr_stun_message *res);
+
+int nr_stun_receive_request_long_term_auth(nr_stun_message *req, nr_stun_server_ctx *ctx, nr_stun_message *res);
+int nr_stun_receive_response_long_term_auth(nr_stun_message *res, nr_stun_client_ctx *ctx);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_reg.h b/media/mtransport/third_party/nICEr/src/stun/stun_reg.h
new file mode 100644
index 000000000..2167fcd91
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_reg.h
@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_reg_h
+#define _stun_reg_h
+#ifdef __cplusplus
+using namespace std;
+extern "C" {
+#endif /* __cplusplus */
+
+#define NR_STUN_REG_PREF_CLNT_RETRANSMIT_TIMEOUT "stun.client.retransmission_timeout"
+#define NR_STUN_REG_PREF_CLNT_RETRANSMIT_BACKOFF "stun.client.retransmission_backoff_factor"
+#define NR_STUN_REG_PREF_CLNT_MAXIMUM_TRANSMITS "stun.client.maximum_transmits"
+#define NR_STUN_REG_PREF_CLNT_FINAL_RETRANSMIT_BACKOFF "stun.client.final_retransmit_backoff"
+
+#define NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS "stun.allow_loopback"
+#define NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS "stun.allow_link_local"
+#define NR_STUN_REG_PREF_ADDRESS_PRFX "stun.address"
+#define NR_STUN_REG_PREF_SERVER_NAME "stun.server.name"
+#define NR_STUN_REG_PREF_SERVER_NONCE_SIZE "stun.server.nonce_size"
+#define NR_STUN_REG_PREF_SERVER_REALM "stun.server.realm"
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c
new file mode 100644
index 000000000..3bfa1674b
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.c
@@ -0,0 +1,472 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_server_ctx.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <string.h>
+#include <assert.h>
+
+#include "nr_api.h"
+#include "stun.h"
+
+static int nr_stun_server_destroy_client(nr_stun_server_client *clnt);
+static int nr_stun_server_send_response(nr_stun_server_ctx *ctx, nr_socket *sock, nr_transport_addr *peer_addr, nr_stun_message *res, nr_stun_server_client *clnt);
+static int nr_stun_server_process_request_auth_checks(nr_stun_server_ctx *ctx, nr_stun_message *req, int auth_rule, nr_stun_message *res);
+
+
+int nr_stun_server_ctx_create(char *label, nr_socket *sock, nr_stun_server_ctx **ctxp)
+ {
+ int r,_status;
+ nr_stun_server_ctx *ctx=0;
+
+ if ((r=nr_stun_startup()))
+ ABORT(r);
+
+ if(!(ctx=RCALLOC(sizeof(nr_stun_server_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(ctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+ ctx->sock=sock;
+ nr_socket_getaddr(sock,&ctx->my_addr);
+
+ STAILQ_INIT(&ctx->clients);
+
+ *ctxp=ctx;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp)
+ {
+ nr_stun_server_ctx *ctx;
+ nr_stun_server_client *clnt1,*clnt2;
+
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ ctx=*ctxp;
+
+ STAILQ_FOREACH_SAFE(clnt1, &ctx->clients, entry, clnt2) {
+ nr_stun_server_destroy_client(clnt1);
+ }
+
+ nr_stun_server_destroy_client(ctx->default_client);
+
+ RFREE(ctx->label);
+ RFREE(ctx);
+
+ return(0);
+ }
+
+static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg, nr_stun_server_client **clntp)
+ {
+ nr_stun_server_client *clnt=0;
+ int r,_status;
+
+ if(!(clnt=RCALLOC(sizeof(nr_stun_server_client))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(clnt->label=r_strdup(client_label)))
+ ABORT(R_NO_MEMORY);
+
+ if(!(clnt->username=r_strdup(user)))
+ ABORT(R_NO_MEMORY);
+
+ if(r=r_data_copy(&clnt->password,pass))
+ ABORT(r);
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s)/CLIENT(%s): Adding client for %s",ctx->label, client_label, user);
+ clnt->stun_server_cb=cb;
+ clnt->cb_arg=cb_arg;
+
+ *clntp = clnt;
+ _status=0;
+ abort:
+ if(_status){
+ nr_stun_server_destroy_client(clnt);
+ }
+ return(_status);
+ }
+
+int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg)
+ {
+ int r,_status;
+ nr_stun_server_client *clnt;
+
+ if (r=nr_stun_server_client_create(ctx, client_label, user, pass, cb, cb_arg, &clnt))
+ ABORT(r);
+
+ STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_stun_server_add_default_client(nr_stun_server_ctx *ctx, char *ufrag, Data *pass, nr_stun_server_cb cb, void *cb_arg)
+ {
+ int r,_status;
+ nr_stun_server_client *clnt;
+
+ assert(!ctx->default_client);
+ if (ctx->default_client)
+ ABORT(R_INTERNAL);
+
+ if (r=nr_stun_server_client_create(ctx, "default_client", ufrag, pass, cb, cb_arg, &clnt))
+ ABORT(r);
+
+ ctx->default_client = clnt;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_stun_server_remove_client(nr_stun_server_ctx *ctx, void *cb_arg)
+ {
+ nr_stun_server_client *clnt1,*clnt2;
+ int found = 0;
+
+ STAILQ_FOREACH_SAFE(clnt1, &ctx->clients, entry, clnt2) {
+ if(clnt1->cb_arg == cb_arg) {
+ STAILQ_REMOVE(&ctx->clients, clnt1, nr_stun_server_client_, entry);
+ nr_stun_server_destroy_client(clnt1);
+ found++;
+ }
+ }
+
+ if (!found)
+ ERETURN(R_NOT_FOUND);
+
+ return 0;
+ }
+
+static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
+ {
+ int _status;
+ nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
+ nr_stun_server_client *clnt = 0;
+ nr_stun_message_attribute *username_attribute;
+
+ if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
+ if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Missing Username",ctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ /* Although this is an exceptional condition, we'll already have seen a
+ * NOTICE-level log message about the unknown user, so additional log
+ * messages at any level higher than DEBUG are unnecessary. */
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Unable to find password for unknown user: %s",ctx->label,username_attribute->u.username);
+ ABORT(R_NOT_FOUND);
+ }
+
+ *password = &clnt->password;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_stun_server_process_request_auth_checks(nr_stun_server_ctx *ctx, nr_stun_message *req, int auth_rule, nr_stun_message *res)
+ {
+ int r,_status;
+
+ if (nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)
+ || !(auth_rule & NR_STUN_AUTH_RULE_OPTIONAL)) {
+ /* favor long term credentials over short term, if both are supported */
+
+ if (auth_rule & NR_STUN_AUTH_RULE_LONG_TERM) {
+ if ((r=nr_stun_receive_request_long_term_auth(req, ctx, res)))
+ ABORT(r);
+ }
+ else if (auth_rule & NR_STUN_AUTH_RULE_SHORT_TERM) {
+ if ((r=nr_stun_receive_request_or_indication_short_term_auth(req, res)))
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, char *msg, int len, nr_transport_addr *peer_addr, int auth_rule)
+ {
+ int r,_status;
+ char string[256];
+ nr_stun_message *req = 0;
+ nr_stun_message *res = 0;
+ nr_stun_server_client *clnt = 0;
+ nr_stun_server_request info;
+ int error;
+ int dont_free = 0;
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Received(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
+
+ snprintf(string, sizeof(string)-1, "STUN-SERVER(%s): Received ", ctx->label);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)msg, len);
+
+ memset(&info,0,sizeof(info));
+
+ if ((r=nr_stun_message_create2(&req, (UCHAR*)msg, len)))
+ ABORT(r);
+
+ if ((r=nr_stun_message_create(&res)))
+ ABORT(r);
+
+ if ((r=nr_stun_decode_message(req, nr_stun_server_get_password, ctx))) {
+ /* RFC5389 S 7.3 says "If any errors are detected, the message is
+ * silently discarded." */
+#ifndef USE_STUN_PEDANTIC
+ /* ... but that seems like a bad idea, at least return a 400 so
+ * that the server isn't a black hole to the client */
+ nr_stun_form_error_response(req, res, 400, "Bad Request - Failed to decode request");
+ ABORT(R_ALREADY);
+#endif /* USE_STUN_PEDANTIC */
+ ABORT(R_REJECTED);
+ }
+
+ if ((r=nr_stun_receive_message(0, req))) {
+ /* RFC5389 S 7.3 says "If any errors are detected, the message is
+ * silently discarded." */
+#ifndef USE_STUN_PEDANTIC
+ /* ... but that seems like a bad idea, at least return a 400 so
+ * that the server isn't a black hole to the client */
+ nr_stun_form_error_response(req, res, 400, "Bad Request - Section 7.3 check failed");
+ ABORT(R_ALREADY);
+#endif /* USE_STUN_PEDANTIC */
+ ABORT(R_REJECTED);
+ }
+
+ if (NR_STUN_GET_TYPE_CLASS(req->header.type) != NR_CLASS_REQUEST
+ && NR_STUN_GET_TYPE_CLASS(req->header.type) != NR_CLASS_INDICATION) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Illegal message type: %04x",ctx->label,req->header.type);
+ /* RFC5389 S 7.3 says "If any errors are detected, the message is
+ * silently discarded." */
+#ifndef USE_STUN_PEDANTIC
+ /* ... but that seems like a bad idea, at least return a 400 so
+ * that the server isn't a black hole to the client */
+ nr_stun_form_error_response(req, res, 400, "Bad Request - Unsupported message type");
+ ABORT(R_ALREADY);
+#endif /* USE_STUN_PEDANTIC */
+ ABORT(R_REJECTED);
+ }
+
+ /* "The STUN agent then does any checks that are required by a
+ * authentication mechanism that the usage has specified" */
+ if ((r=nr_stun_server_process_request_auth_checks(ctx, req, auth_rule, res)))
+ ABORT(r);
+
+ if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_INDICATION) {
+ if ((r=nr_stun_process_indication(req)))
+ ABORT(r);
+ }
+ else {
+ if ((r=nr_stun_process_request(req, res)))
+ ABORT(r);
+ }
+
+ assert(res->header.type == 0);
+
+ clnt = 0;
+ if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_REQUEST) {
+ if ((nr_stun_get_message_client(ctx, req, &clnt))) {
+ if ((r=nr_stun_form_success_response(req, peer_addr, 0, res)))
+ ABORT(r);
+ }
+ else {
+ if ((r=nr_stun_form_success_response(req, peer_addr, &clnt->password, res)))
+ ABORT(r);
+ }
+ }
+
+ if(clnt && clnt->stun_server_cb){
+ r_log(NR_LOG_STUN,LOG_DEBUG,"Entering STUN server callback");
+
+ /* Set up the info */
+ if(r=nr_transport_addr_copy(&info.src_addr,peer_addr))
+ ABORT(r);
+
+ info.request = req;
+ info.response = res;
+
+ error = 0;
+ dont_free = 0;
+ if (clnt->stun_server_cb(clnt->cb_arg,ctx,sock,&info,&dont_free,&error)) {
+ if (error == 0)
+ error = 500;
+
+ nr_stun_form_error_response(req, res, error, "ICE Failure");
+ ABORT(R_ALREADY);
+ }
+ }
+
+ _status=0;
+ abort:
+ if (!res)
+ goto skip_response;
+
+ if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_INDICATION)
+ goto skip_response;
+
+ /* Now respond */
+
+ if (_status != 0 && ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0))
+ nr_stun_form_error_response(req, res, 500, "Failed to specify error");
+
+ if ((r=nr_stun_server_send_response(ctx, sock, peer_addr, res, clnt))) {
+ r_log(NR_LOG_STUN,LOG_ERR,"STUN-SERVER(label=%s): Failed sending response (my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
+ _status = R_FAILED;
+ }
+
+#if 0
+ /* EKR: suppressed these checks because if you have an error when
+ you are sending an error, things go wonky */
+#ifdef SANITY_CHECKS
+ if (_status == R_ALREADY) {
+ assert(NR_STUN_GET_TYPE_CLASS(res->header.type) == NR_CLASS_ERROR_RESPONSE);
+ assert(nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0));
+ }
+ else {
+ assert(NR_STUN_GET_TYPE_CLASS(res->header.type) == NR_CLASS_RESPONSE);
+ assert(!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0));
+ }
+#endif /* SANITY_CHECKS */
+#endif
+
+ if (0) {
+ skip_response:
+ _status = 0;
+ }
+
+ if (!dont_free) {
+ nr_stun_message_destroy(&res);
+ nr_stun_message_destroy(&req);
+ }
+
+ return(_status);
+ }
+
+static int nr_stun_server_send_response(nr_stun_server_ctx *ctx, nr_socket *sock, nr_transport_addr *peer_addr, nr_stun_message *res, nr_stun_server_client *clnt)
+ {
+ int r,_status;
+ Data *hmacPassword;
+ char string[256];
+
+ r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(label=%s): Sending(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
+
+ if (clnt) {
+ hmacPassword = &clnt->password;
+ }
+ else {
+ hmacPassword = 0;
+ }
+
+ if ((r=nr_stun_encode_message(res))) {
+ /* should never happen */
+ r_log(NR_LOG_STUN,LOG_ERR,"STUN-SERVER(label=%s): Unable to encode message", ctx->label);
+ }
+ else {
+ snprintf(string, sizeof(string)-1, "STUN(%s): Sending to %s ", ctx->label, peer_addr->as_string);
+ r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)res->buffer, res->length);
+
+ if(r=nr_socket_sendto(sock?sock:ctx->sock,res->buffer,res->length,0,peer_addr))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_stun_server_destroy_client(nr_stun_server_client *clnt)
+ {
+ if (!clnt)
+ return 0;
+
+ RFREE(clnt->label);
+ RFREE(clnt->username);
+ r_data_zfree(&clnt->password);
+
+ RFREE(clnt);
+ return(0);
+ }
+
+int nr_stun_get_message_client(nr_stun_server_ctx *ctx, nr_stun_message *req, nr_stun_server_client **out)
+ {
+ int _status;
+ nr_stun_message_attribute *attr;
+ nr_stun_server_client *clnt=0;
+
+ if (! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, &attr)) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Missing Username",ctx->label);
+ ABORT(R_NOT_FOUND);
+ }
+
+ STAILQ_FOREACH(clnt, &ctx->clients, entry) {
+ if (!strncmp(clnt->username, attr->u.username,
+ sizeof(attr->u.username)))
+ break;
+ }
+
+ if (!clnt && ctx->default_client) {
+ /* If we can't find a specific client see if this matches the default,
+ which means that the username starts with our ufrag.
+ */
+ char *colon = strchr(attr->u.username, ':');
+ if (colon && !strncmp(ctx->default_client->username,
+ attr->u.username,
+ colon - attr->u.username)) {
+ clnt = ctx->default_client;
+ r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Falling back to default client, username=: %s",ctx->label,attr->u.username);
+ }
+ }
+
+ if (!clnt) {
+ r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Request from unknown user: %s",ctx->label,attr->u.username);
+ ABORT(R_NOT_FOUND);
+ }
+
+ *out = clnt;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.h b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.h
new file mode 100644
index 000000000..343e67606
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_server_ctx.h
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_server_ctx_h
+#define _stun_server_ctx_h
+
+typedef struct nr_stun_server_ctx_ nr_stun_server_ctx;
+typedef struct nr_stun_server_client_ nr_stun_server_client;
+
+#include "stun_util.h"
+
+
+typedef struct nr_stun_server_request_{
+ nr_transport_addr src_addr;
+ nr_stun_message *request;
+ nr_stun_message *response;
+} nr_stun_server_request;
+
+typedef int (*nr_stun_server_cb)(void *cb_arg, struct nr_stun_server_ctx_ *ctx,nr_socket *sock,nr_stun_server_request *req, int *dont_free, int *error);
+
+struct nr_stun_server_client_ {
+ char *label;
+ char *username;
+ Data password;
+ nr_stun_server_cb stun_server_cb;
+ void *cb_arg;
+ char nonce[NR_STUN_MAX_NONCE_BYTES+1]; /* +1 for \0 */
+ STAILQ_ENTRY(nr_stun_server_client_) entry;
+};
+
+typedef STAILQ_HEAD(nr_stun_server_client_head_, nr_stun_server_client_) nr_stun_server_client_head;
+
+struct nr_stun_server_ctx_ {
+ char *label;
+ nr_socket *sock;
+ nr_transport_addr my_addr;
+ nr_stun_server_client_head clients;
+ nr_stun_server_client *default_client;
+};
+
+
+int nr_stun_server_ctx_create(char *label, nr_socket *sock, nr_stun_server_ctx **ctxp);
+int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp);
+int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg);
+int nr_stun_server_remove_client(nr_stun_server_ctx *ctx, void *cb_arg);
+int nr_stun_server_add_default_client(nr_stun_server_ctx *ctx, char *ufrag, Data *pass, nr_stun_server_cb cb, void *cb_arg);
+int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, char *msg, int len, nr_transport_addr *peer_addr, int auth_rule);
+int nr_stun_get_message_client(nr_stun_server_ctx *ctx, nr_stun_message *req, nr_stun_server_client **clnt);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_util.c b/media/mtransport/third_party/nICEr/src/stun/stun_util.c
new file mode 100644
index 000000000..e347e542f
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_util.c
@@ -0,0 +1,322 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+static char *RCSSTRING __UNUSED__="$Id: stun_util.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <stdlib.h>
+#include <io.h>
+#include <time.h>
+#else /* UNIX */
+#include <string.h>
+#endif /* end UNIX */
+#include <assert.h>
+
+#include "stun.h"
+#include "stun_reg.h"
+#include "registry.h"
+#include "addrs.h"
+#include "transport_addr_reg.h"
+#include "nr_crypto.h"
+#include "hex.h"
+
+
+int NR_LOG_STUN = 0;
+
+int
+nr_stun_startup(void)
+{
+ int r,_status;
+
+ if ((r=r_log_register("stun", &NR_LOG_STUN)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+int
+nr_stun_xor_mapped_address(UINT4 magicCookie, UINT12 transactionId, nr_transport_addr *from, nr_transport_addr *to)
+{
+ int _status;
+
+ switch (from->ip_version) {
+ case NR_IPV4:
+ nr_ip4_port_to_transport_addr(
+ (ntohl(from->u.addr4.sin_addr.s_addr) ^ magicCookie),
+ (ntohs(from->u.addr4.sin_port) ^ (magicCookie>>16)),
+ from->protocol, to);
+ break;
+ case NR_IPV6:
+ {
+ union {
+ unsigned char addr[16];
+ UINT4 addr32[4];
+ } maskedAddr;
+
+ maskedAddr.addr32[0] = htonl(magicCookie); /* Passed in host byte order */
+ memcpy(&maskedAddr.addr32[1], transactionId.octet, sizeof(transactionId));
+
+ /* We now have the mask in network byte order */
+ /* Xor the address in network byte order */
+ for (int i = 0; i < sizeof(maskedAddr); ++i) {
+ maskedAddr.addr[i] ^= from->u.addr6.sin6_addr.s6_addr[i];
+ }
+
+ nr_ip6_port_to_transport_addr(
+ (struct in6_addr*)&maskedAddr,
+ (ntohs(from->u.addr6.sin6_port) ^ (magicCookie>>16)),
+ from->protocol, to);
+ }
+ break;
+ default:
+ assert(0);
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+int
+nr_stun_find_local_addresses(nr_local_addr addrs[], int maxaddrs, int *count)
+{
+ int r,_status;
+ //NR_registry *children = 0;
+
+ *count = 0;
+
+ if ((r=NR_reg_get_child_count(NR_STUN_REG_PREF_ADDRESS_PRFX, (unsigned int*)count)))
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+
+ if (*count == 0) {
+ char allow_loopback;
+ char allow_link_local;
+
+ if ((r=NR_reg_get_char(NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, &allow_loopback))) {
+ if (r == R_NOT_FOUND)
+ allow_loopback = 0;
+ else
+ ABORT(r);
+ }
+
+ if ((r=NR_reg_get_char(NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, &allow_link_local))) {
+ if (r == R_NOT_FOUND)
+ allow_link_local = 0;
+ else
+ ABORT(r);
+ }
+
+ if ((r=nr_stun_get_addrs(addrs, maxaddrs, !allow_loopback, !allow_link_local, count)))
+ ABORT(r);
+
+ goto done;
+ }
+
+ if (*count >= maxaddrs) {
+ r_log(NR_LOG_STUN, LOG_INFO, "Address list truncated from %d to %d", *count, maxaddrs);
+ *count = maxaddrs;
+ }
+
+#if 0
+ if (*count > 0) {
+ /* TODO(ekr@rtfm.com): Commented out 2012-07-26.
+
+ This code is currently not used in Firefox and needs to be
+ ported to 64-bit */
+ children = RCALLOC((*count + 10) * sizeof(*children));
+ if (!children)
+ ABORT(R_NO_MEMORY);
+
+ assert(sizeof(size_t) == sizeof(*count));
+
+ if ((r=NR_reg_get_children(NR_STUN_REG_PREF_ADDRESS_PRFX, children, (size_t)(*count + 10), (size_t*)count)))
+ ABORT(r);
+
+ for (i = 0; i < *count; ++i) {
+ if ((r=nr_reg_get_transport_addr(children[i], 0, &addrs[i].addr)))
+ ABORT(r);
+ }
+ }
+#endif
+
+ done:
+
+ _status=0;
+ abort:
+ //RFREE(children);
+ return _status;
+}
+
+int
+nr_stun_different_transaction(UCHAR *msg, int len, nr_stun_message *req)
+{
+ int _status;
+ nr_stun_message_header header;
+ char reqid[44];
+ char msgid[44];
+ int len2;
+
+ if (sizeof(header) > len)
+ ABORT(R_FAILED);
+
+ assert(sizeof(header.id) == sizeof(UINT12));
+
+ memcpy(&header, msg, sizeof(header));
+
+ if (memcmp(&req->header.id, &header.id, sizeof(header.id))) {
+ nr_nbin2hex((UCHAR*)&req->header.id, sizeof(req->header.id), reqid, sizeof(reqid), &len2);
+ nr_nbin2hex((UCHAR*)&header.id, sizeof(header.id), msgid, sizeof(msgid), &len2);
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Mismatched message IDs %s/%s", reqid, msgid);
+ ABORT(R_NOT_FOUND);
+ }
+
+ _status=0;
+ abort:
+ return _status;
+}
+
+char*
+nr_stun_msg_type(int type)
+{
+ char *ret = 0;
+
+ switch (type) {
+ case NR_STUN_MSG_BINDING_REQUEST:
+ ret = "BINDING-REQUEST";
+ break;
+ case NR_STUN_MSG_BINDING_INDICATION:
+ ret = "BINDING-INDICATION";
+ break;
+ case NR_STUN_MSG_BINDING_RESPONSE:
+ ret = "BINDING-RESPONSE";
+ break;
+ case NR_STUN_MSG_BINDING_ERROR_RESPONSE:
+ ret = "BINDING-ERROR-RESPONSE";
+ break;
+
+#ifdef USE_TURN
+ case NR_STUN_MSG_ALLOCATE_REQUEST:
+ ret = "ALLOCATE-REQUEST";
+ break;
+ case NR_STUN_MSG_ALLOCATE_RESPONSE:
+ ret = "ALLOCATE-RESPONSE";
+ break;
+ case NR_STUN_MSG_ALLOCATE_ERROR_RESPONSE:
+ ret = "ALLOCATE-ERROR-RESPONSE";
+ break;
+ case NR_STUN_MSG_REFRESH_REQUEST:
+ ret = "REFRESH-REQUEST";
+ break;
+ case NR_STUN_MSG_REFRESH_RESPONSE:
+ ret = "REFRESH-RESPONSE";
+ break;
+ case NR_STUN_MSG_REFRESH_ERROR_RESPONSE:
+ ret = "REFRESH-ERROR-RESPONSE";
+ break;
+ case NR_STUN_MSG_SEND_INDICATION:
+ ret = "SEND-INDICATION";
+ break;
+ case NR_STUN_MSG_DATA_INDICATION:
+ ret = "DATA-INDICATION";
+ break;
+ case NR_STUN_MSG_PERMISSION_REQUEST:
+ ret = "PERMISSION-REQUEST";
+ break;
+ case NR_STUN_MSG_PERMISSION_RESPONSE:
+ ret = "PERMISSION-RESPONSE";
+ break;
+ case NR_STUN_MSG_PERMISSION_ERROR_RESPONSE:
+ ret = "PERMISSION-ERROR-RESPONSE";
+ break;
+#endif /* USE_TURN */
+
+ default:
+ /* ret remains 0 */
+ break;
+ }
+
+ return ret;
+}
+
+int
+nr_random_alphanum(char *alphanum, int size)
+{
+ static char alphanums[256] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
+ int i;
+
+ nr_crypto_random_bytes((UCHAR*)alphanum, size);
+
+ /* now convert from binary to alphanumeric */
+ for (i = 0; i < size; ++i)
+ alphanum[i] = alphanums[(UCHAR)alphanum[i]];
+
+ return 0;
+}
diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_util.h b/media/mtransport/third_party/nICEr/src/stun/stun_util.h
new file mode 100644
index 000000000..c57e84d12
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/stun_util.h
@@ -0,0 +1,56 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _stun_util_h
+#define _stun_util_h
+
+#include "stun.h"
+#include "local_addr.h"
+
+extern int NR_LOG_STUN;
+
+int nr_stun_startup(void);
+
+int nr_stun_xor_mapped_address(UINT4 magicCookie, UINT12 transactionId, nr_transport_addr *from, nr_transport_addr *to);
+
+int nr_stun_find_local_addresses(nr_local_addr addrs[], int maxaddrs, int *count);
+
+int nr_stun_different_transaction(UCHAR *msg, int len, nr_stun_message *req);
+
+char* nr_stun_msg_type(int type);
+
+int nr_random_alphanum(char *alphanum, int size);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
new file mode 100644
index 000000000..c873f6faf
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
@@ -0,0 +1,1056 @@
+/*
+ Copyright (c) 2007, Adobe Systems, Incorporated
+ Copyright (c) 2013, Mozilla
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: turn_client_ctx.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
+
+#ifdef USE_TURN
+
+#include <assert.h>
+#include <string.h>
+
+#include "nr_api.h"
+#include "r_time.h"
+#include "async_timer.h"
+#include "nr_socket_buffered_stun.h"
+#include "stun.h"
+#include "turn_client_ctx.h"
+
+int NR_LOG_TURN = 0;
+
+#define TURN_MAX_PENDING_BYTES 32000
+
+#define TURN_RTO 100 /* Hardcoded RTO estimate */
+#define TURN_LIFETIME_REQUEST_SECONDS 3600 /* One hour */
+#define TURN_USECS_PER_S 1000000
+#define TURN_REFRESH_SLACK_SECONDS 10 /* How long before expiry to refresh
+ allocations/permissions. The RFC 5766
+ Section 7 recommendation if 60 seconds,
+ but this is silly since the transaction
+ times out after about 5. */
+#define TURN_PERMISSION_LIFETIME_SECONDS 300 /* 5 minutes. From RFC 5766 2.3 */
+
+// Set to enable a temporary fix that will run the TURN reservation keep-alive
+// logic when data is received via a TURN relayed path: a DATA_INDICATION packet is received.
+// TODO(pkerr@mozilla.com) This should be replace/removed when bug 935806 is implemented.
+#define REFRESH_RESERVATION_ON_RECV 1
+
+static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int type,
+ NR_async_cb success_cb,
+ NR_async_cb failure_cb,
+ nr_turn_stun_ctx **ctxp);
+static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp);
+static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg);
+static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx,
+ char *realm, char *nonce);
+static void nr_turn_client_refresh_timer_cb(NR_SOCKET s, int how, void *arg);
+static int nr_turn_client_refresh_setup(nr_turn_client_ctx *ctx,
+ nr_turn_stun_ctx **sctx);
+static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *ctx,
+ nr_turn_stun_ctx *sctx,
+ UINT4 lifetime);
+static int nr_turn_permission_create(nr_turn_client_ctx *ctx,
+ nr_transport_addr *addr,
+ nr_turn_permission **permp);
+static int nr_turn_permission_find(nr_turn_client_ctx *ctx,
+ nr_transport_addr *addr,
+ nr_turn_permission **permp);
+static int nr_turn_permission_destroy(nr_turn_permission **permp);
+static void nr_turn_client_refresh_cb(NR_SOCKET s, int how, void *arg);
+static void nr_turn_client_permissions_cb(NR_SOCKET s, int how, void *cb);
+static int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
+ nr_stun_message *req,
+ int flags);
+
+
+/* nr_turn_stun_ctx functions */
+static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int mode,
+ NR_async_cb success_cb,
+ NR_async_cb error_cb,
+ nr_turn_stun_ctx **ctxp)
+{
+ nr_turn_stun_ctx *sctx = 0;
+ int r,_status;
+ char label[256];
+
+ if (!(sctx=RCALLOC(sizeof(nr_turn_stun_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ /* TODO(ekr@rtfm.com): label by phase */
+ snprintf(label, sizeof(label), "%s:%s", tctx->label, ":TURN");
+
+ if ((r=nr_stun_client_ctx_create(label, tctx->sock, &tctx->turn_server_addr,
+ TURN_RTO, &sctx->stun))) {
+ ABORT(r);
+ }
+
+ /* Set the STUN auth parameters, but don't set authentication on.
+ For that we need the nonce, set in nr_turn_stun_set_auth_params.
+ */
+ sctx->stun->auth_params.username=tctx->username;
+ INIT_DATA(sctx->stun->auth_params.password,
+ tctx->password->data, tctx->password->len);
+
+ sctx->tctx=tctx;
+ sctx->success_cb=success_cb;
+ sctx->error_cb=error_cb;
+ sctx->mode=mode;
+ sctx->last_error_code=0;
+
+ /* Add ourselves to the tctx's list */
+ STAILQ_INSERT_TAIL(&tctx->stun_ctxs, sctx, entry);
+ *ctxp=sctx;
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_stun_ctx_destroy(&sctx);
+ }
+ return(_status);
+}
+
+/* Note: this function does not pull us off the tctx's list. */
+static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp)
+{
+ nr_turn_stun_ctx *ctx;
+
+ if (!ctxp || !*ctxp)
+ return 0;
+
+ ctx = *ctxp;
+ *ctxp = 0;
+
+ nr_stun_client_ctx_destroy(&ctx->stun);
+ RFREE(ctx->realm);
+ RFREE(ctx->nonce);
+
+ RFREE(ctx);
+
+ return 0;
+}
+
+static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx,
+ char *realm, char *nonce)
+{
+ int _status;
+
+ RFREE(ctx->realm);
+ RFREE(ctx->nonce);
+
+ assert(realm);
+ if (!realm)
+ ABORT(R_BAD_ARGS);
+ ctx->realm=r_strdup(realm);
+ if (!ctx->realm)
+ ABORT(R_NO_MEMORY);
+
+ assert(nonce);
+ if (!nonce)
+ ABORT(R_BAD_ARGS);
+ ctx->nonce=r_strdup(nonce);
+ if (!ctx->nonce)
+ ABORT(R_NO_MEMORY);
+
+ RFREE(ctx->stun->realm);
+ ctx->stun->realm = r_strdup(ctx->realm);
+ if (!ctx->stun->realm)
+ ABORT(R_NO_MEMORY);
+
+ ctx->stun->auth_params.realm = ctx->realm;
+ ctx->stun->auth_params.nonce = ctx->nonce;
+ ctx->stun->auth_params.authenticate = 1; /* May already be 1 */
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_turn_stun_ctx_start(nr_turn_stun_ctx *ctx)
+{
+ int r, _status;
+ nr_turn_client_ctx *tctx = ctx->tctx;
+
+ if ((r=nr_stun_client_reset(ctx->stun))) {
+ r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't reset STUN",
+ tctx->label);
+ ABORT(r);
+ }
+
+ if ((r=nr_stun_client_start(ctx->stun, ctx->mode, nr_turn_stun_ctx_cb, ctx))) {
+ r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't start STUN",
+ tctx->label);
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ return _status;
+}
+
+static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg)
+{
+ int r, _status;
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+
+ ctx->last_error_code = ctx->stun->error_code;
+
+ switch (ctx->stun->state) {
+ case NR_STUN_CLIENT_STATE_DONE:
+ /* Save the realm and nonce */
+ if (ctx->stun->realm && (!ctx->tctx->realm || strcmp(ctx->stun->realm,
+ ctx->tctx->realm))) {
+ RFREE(ctx->tctx->realm);
+ ctx->tctx->realm = r_strdup(ctx->stun->realm);
+ if (!ctx->tctx->realm)
+ ABORT(R_NO_MEMORY);
+ }
+ if (ctx->stun->nonce && (!ctx->tctx->nonce || strcmp(ctx->stun->nonce,
+ ctx->tctx->nonce))) {
+ RFREE(ctx->tctx->nonce);
+ ctx->tctx->nonce = r_strdup(ctx->stun->nonce);
+ if (!ctx->tctx->nonce)
+ ABORT(R_NO_MEMORY);
+ }
+
+ ctx->retry_ct=0;
+ ctx->success_cb(0, 0, ctx);
+ break;
+
+ case NR_STUN_CLIENT_STATE_FAILED:
+ /* Special case: if this is an authentication error,
+ we retry once. This allows the 401/438 nonce retry
+ paradigm. After that, we fail */
+ /* TODO(ekr@rtfm.com): 401 needs a #define */
+ /* TODO(ekr@rtfm.com): Add alternate-server (Mozilla bug 857688) */
+ if (ctx->stun->error_code == 401 || ctx->stun->error_code == 438) {
+ if (ctx->retry_ct > 0) {
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Exceeded the number of retries", ctx->tctx->label);
+ ABORT(R_FAILED);
+ }
+
+ if (!ctx->stun->nonce) {
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): 401 but no nonce", ctx->tctx->label);
+ ABORT(R_FAILED);
+ }
+ if (!ctx->stun->realm) {
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): 401 but no realm", ctx->tctx->label);
+ ABORT(R_FAILED);
+ }
+
+ /* Try to retry */
+ if ((r=nr_turn_stun_set_auth_params(ctx, ctx->stun->realm,
+ ctx->stun->nonce)))
+ ABORT(r);
+
+ ctx->stun->error_code = 0; /* Reset to avoid inf-looping */
+
+ if ((r=nr_turn_stun_ctx_start(ctx))) {
+ r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't start STUN", ctx->tctx->label);
+ ABORT(r);
+ }
+
+ ctx->retry_ct++;
+ }
+ else {
+ ABORT(R_FAILED);
+ }
+ break;
+
+ case NR_STUN_CLIENT_STATE_TIMED_OUT:
+ ABORT(R_FAILED);
+ break;
+
+ case NR_STUN_CLIENT_STATE_CANCELLED:
+ assert(0); /* Shouldn't happen */
+ return;
+ break;
+
+ default:
+ assert(0); /* Shouldn't happen */
+ return;
+ }
+
+ _status=0;
+abort:
+ if (_status) {
+ ctx->error_cb(0, 0, ctx);
+ }
+}
+
+/* nr_turn_client_ctx functions */
+int nr_turn_client_ctx_create(const char *label, nr_socket *sock,
+ const char *username, Data *password,
+ nr_transport_addr *addr,
+ nr_turn_client_ctx **ctxp)
+{
+ nr_turn_client_ctx *ctx=0;
+ int r,_status;
+
+ if ((r=r_log_register("turn", &NR_LOG_TURN)))
+ ABORT(r);
+
+ if(!(ctx=RCALLOC(sizeof(nr_turn_client_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ STAILQ_INIT(&ctx->stun_ctxs);
+ STAILQ_INIT(&ctx->permissions);
+
+ if(!(ctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+
+ ctx->sock=sock;
+ ctx->username = r_strdup(username);
+ if (!ctx->username)
+ ABORT(R_NO_MEMORY);
+
+ if ((r=r_data_create(&ctx->password, password->data, password->len)))
+ ABORT(r);
+ if ((r=nr_transport_addr_copy(&ctx->turn_server_addr, addr)))
+ ABORT(r);
+
+ ctx->state = NR_TURN_CLIENT_STATE_INITTED;
+ if (addr->protocol == IPPROTO_TCP) {
+ if ((r=nr_socket_connect(ctx->sock, &ctx->turn_server_addr))) {
+ if (r != R_WOULDBLOCK)
+ ABORT(r);
+ }
+ }
+
+ *ctxp=ctx;
+
+ _status=0;
+abort:
+ if(_status){
+ nr_turn_client_ctx_destroy(&ctx);
+ }
+ return(_status);
+}
+
+int
+nr_turn_client_ctx_destroy(nr_turn_client_ctx **ctxp)
+{
+ nr_turn_client_ctx *ctx;
+
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ ctx=*ctxp;
+ *ctxp = 0;
+
+ if (ctx->label)
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): destroy", ctx->label);
+
+ nr_turn_client_deallocate(ctx);
+
+ /* Cancel frees the rest of our data */
+ RFREE(ctx->label);
+ ctx->label = 0;
+
+ nr_turn_client_cancel(ctx);
+
+ RFREE(ctx->username);
+ ctx->username = 0;
+ r_data_destroy(&ctx->password);
+ RFREE(ctx->nonce);
+ ctx->nonce = 0;
+ RFREE(ctx->realm);
+ ctx->realm = 0;
+
+ /* Destroy the STUN client ctxs */
+ while (!STAILQ_EMPTY(&ctx->stun_ctxs)) {
+ nr_turn_stun_ctx *stun = STAILQ_FIRST(&ctx->stun_ctxs);
+ STAILQ_REMOVE_HEAD(&ctx->stun_ctxs, entry);
+ nr_turn_stun_ctx_destroy(&stun);
+ }
+
+ /* Destroy the permissions */
+ while (!STAILQ_EMPTY(&ctx->permissions)) {
+ nr_turn_permission *perm = STAILQ_FIRST(&ctx->permissions);
+ STAILQ_REMOVE_HEAD(&ctx->permissions, entry);
+ nr_turn_permission_destroy(&perm);
+ }
+
+ RFREE(ctx);
+
+ return(0);
+}
+
+int nr_turn_client_cancel(nr_turn_client_ctx *ctx)
+{
+ nr_turn_stun_ctx *stun = 0;
+
+ if (ctx->state == NR_TURN_CLIENT_STATE_CANCELLED ||
+ ctx->state == NR_TURN_CLIENT_STATE_FAILED)
+ return(0);
+
+ if (ctx->label)
+ r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): cancelling", ctx->label);
+
+ /* Cancel the STUN client ctxs */
+ stun = STAILQ_FIRST(&ctx->stun_ctxs);
+ while (stun) {
+ nr_stun_client_cancel(stun->stun);
+ stun = STAILQ_NEXT(stun, entry);
+ }
+
+ /* Cancel the timers, if not already cancelled */
+ NR_async_timer_cancel(ctx->connected_timer_handle);
+ NR_async_timer_cancel(ctx->refresh_timer_handle);
+
+ ctx->state = NR_TURN_CLIENT_STATE_CANCELLED;
+
+ return(0);
+}
+
+int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
+ nr_stun_message *req,
+ int flags)
+{
+ int r,_status;
+
+ if ((r=nr_stun_encode_message(req)))
+ ABORT(r);
+
+ if ((r=nr_socket_sendto(ctx->sock,
+ req->buffer, req->length, flags,
+ &ctx->turn_server_addr))) {
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): Failed sending request",
+ ctx->label);
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_turn_client_deallocate(nr_turn_client_ctx *ctx)
+{
+ int r,_status;
+ nr_stun_message *aloc = 0;
+ nr_stun_client_auth_params auth;
+ nr_stun_client_refresh_request_params refresh;
+
+ if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
+ return(0);
+
+ r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): deallocating", ctx->label);
+
+ refresh.lifetime_secs = 0;
+
+ auth.username = ctx->username;
+ INIT_DATA(auth.password, ctx->password->data, ctx->password->len);
+
+ auth.realm = ctx->realm;
+ auth.nonce = ctx->nonce;
+
+ auth.authenticate = 1;
+
+ if ((r=nr_stun_build_refresh_request(&auth, &refresh, &aloc)))
+ ABORT(r);
+
+ // We are only sending a single request here because we are in the process of
+ // shutting everything down. Theoretically we should probably start a seperate
+ // STUN transaction which outlives the TURN context.
+ if ((r=nr_turn_client_send_stun_request(ctx, aloc, 0)))
+ ABORT(r);
+
+ ctx->state = NR_TURN_CLIENT_STATE_DEALLOCATING;
+
+ _status=0;
+abort:
+ nr_stun_message_destroy(&aloc);
+ return(_status);
+}
+
+static void nr_turn_client_fire_finished_cb(nr_turn_client_ctx *ctx)
+ {
+ if (ctx->finished_cb) {
+ NR_async_cb finished_cb=ctx->finished_cb;
+ ctx->finished_cb=0;
+ finished_cb(0, 0, ctx->cb_arg);
+ }
+ }
+
+int nr_turn_client_failed(nr_turn_client_ctx *ctx)
+{
+ if (ctx->state == NR_TURN_CLIENT_STATE_FAILED ||
+ ctx->state == NR_TURN_CLIENT_STATE_CANCELLED)
+ return(0);
+
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s) failed", ctx->label);
+ nr_turn_client_cancel(ctx);
+ ctx->state = NR_TURN_CLIENT_STATE_FAILED;
+ nr_turn_client_fire_finished_cb(ctx);
+
+ return(0);
+}
+
+int nr_turn_client_get_relayed_address(nr_turn_client_ctx *ctx,
+ nr_transport_addr *relayed_address)
+{
+ int r, _status;
+
+ if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
+ ABORT(R_FAILED);
+
+ if (r=nr_transport_addr_copy(relayed_address, &ctx->relay_addr))
+ ABORT(r);
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+int nr_turn_client_get_mapped_address(nr_turn_client_ctx *ctx,
+ nr_transport_addr *mapped_address)
+{
+ int r, _status;
+
+ if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
+ ABORT(R_FAILED);
+
+ if (r=nr_transport_addr_copy(mapped_address, &ctx->mapped_addr))
+ ABORT(r);
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static void nr_turn_client_allocate_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+ nr_turn_stun_ctx *refresh_ctx;
+ int r,_status;
+
+ ctx->tctx->state = NR_TURN_CLIENT_STATE_ALLOCATED;
+
+ if ((r=nr_transport_addr_copy(
+ &ctx->tctx->relay_addr,
+ &ctx->stun->results.allocate_response.relay_addr)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(
+ &ctx->tctx->mapped_addr,
+ &ctx->stun->results.allocate_response.mapped_addr)))
+ ABORT(r);
+
+ if ((r=nr_turn_client_refresh_setup(ctx->tctx, &refresh_ctx)))
+ ABORT(r);
+
+ if ((r=nr_turn_client_start_refresh_timer(
+ ctx->tctx, refresh_ctx,
+ ctx->stun->results.allocate_response.lifetime_secs)))
+ ABORT(r);
+
+ r_log(NR_LOG_TURN, LOG_INFO,
+ "TURN(%s): Succesfully allocated addr %s lifetime=%u",
+ ctx->tctx->label,
+ ctx->tctx->relay_addr.as_string,
+ ctx->stun->results.allocate_response.lifetime_secs);
+
+ nr_turn_client_fire_finished_cb(ctx->tctx);
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_client_failed(ctx->tctx);
+ }
+}
+
+static void nr_turn_client_error_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, %s",
+ ctx->tctx->label, ctx->mode, __FUNCTION__);
+
+ nr_turn_client_failed(ctx->tctx);
+}
+
+static void nr_turn_client_permission_error_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+
+ if (ctx->last_error_code == 403) {
+ r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, permission denied",
+ ctx->tctx->label, ctx->mode);
+
+ } else{
+ nr_turn_client_error_cb(0, 0, ctx);
+ }
+}
+
+int nr_turn_client_allocate(nr_turn_client_ctx *ctx,
+ NR_async_cb finished_cb, void *cb_arg)
+{
+ nr_turn_stun_ctx *stun = 0;
+ int r,_status;
+
+ if(ctx->state == NR_TURN_CLIENT_STATE_FAILED ||
+ ctx->state == NR_TURN_CLIENT_STATE_CANCELLED){
+ /* TURN TCP contexts can fail before we ever try to form an allocation,
+ * since the TCP connection can fail. It is also conceivable that a TURN
+ * TCP context could be cancelled before we are done forming all
+ * allocations (although we do not do this at the time this code was
+ * written) */
+ assert(ctx->turn_server_addr.protocol == IPPROTO_TCP);
+ ABORT(R_NOT_FOUND);
+ }
+
+ assert(ctx->state == NR_TURN_CLIENT_STATE_INITTED);
+
+ ctx->finished_cb=finished_cb;
+ ctx->cb_arg=cb_arg;
+
+ if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST,
+ nr_turn_client_allocate_cb,
+ nr_turn_client_error_cb,
+ &stun)))
+ ABORT(r);
+ stun->stun->params.allocate_request.lifetime_secs =
+ TURN_LIFETIME_REQUEST_SECONDS;
+
+ if (ctx->state == NR_TURN_CLIENT_STATE_INITTED) {
+ if ((r=nr_turn_stun_ctx_start(stun)))
+ ABORT(r);
+ ctx->state = NR_TURN_CLIENT_STATE_ALLOCATING;
+ } else {
+ ABORT(R_ALREADY);
+ }
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_client_failed(ctx);
+ }
+
+ return(_status);
+}
+
+int nr_turn_client_process_response(nr_turn_client_ctx *ctx,
+ UCHAR *msg, int len,
+ nr_transport_addr *turn_server_addr)
+{
+ int r, _status;
+ nr_turn_stun_ctx *sc1;
+
+ switch (ctx->state) {
+ case NR_TURN_CLIENT_STATE_ALLOCATING:
+ case NR_TURN_CLIENT_STATE_ALLOCATED:
+ break;
+ default:
+ ABORT(R_FAILED);
+ }
+
+ sc1 = STAILQ_FIRST(&ctx->stun_ctxs);
+ while (sc1) {
+ r = nr_stun_client_process_response(sc1->stun, msg, len, turn_server_addr);
+ if (!r)
+ break;
+ if (r==R_RETRY) /* Likely a 401 and we will retry */
+ break;
+ if (r != R_REJECTED)
+ ABORT(r);
+ sc1 = STAILQ_NEXT(sc1, entry);
+ }
+ if (!sc1)
+ ABORT(R_REJECTED);
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_turn_client_refresh_setup(nr_turn_client_ctx *ctx,
+ nr_turn_stun_ctx **sctx)
+{
+ nr_turn_stun_ctx *stun = 0;
+ int r,_status;
+
+ assert(ctx->state == NR_TURN_CLIENT_STATE_ALLOCATED);
+ if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
+ ABORT(R_NOT_PERMITTED);
+
+ if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_REFRESH_REQUEST,
+ nr_turn_client_refresh_cb,
+ nr_turn_client_error_cb,
+ &stun)))
+ ABORT(r);
+
+ if ((r=nr_turn_stun_set_auth_params(stun, ctx->realm, ctx->nonce)))
+ ABORT(r);
+
+ stun->stun->params.refresh_request.lifetime_secs =
+ TURN_LIFETIME_REQUEST_SECONDS;
+
+
+ *sctx=stun;
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_turn_client_start_refresh_timer(nr_turn_client_ctx *tctx,
+ nr_turn_stun_ctx *sctx,
+ UINT4 lifetime)
+{
+ int _status;
+
+ assert(!tctx->refresh_timer_handle);
+
+ if (lifetime <= TURN_REFRESH_SLACK_SECONDS) {
+ r_log(NR_LOG_TURN, LOG_ERR, "Too short lifetime specified for turn %u", lifetime);
+ ABORT(R_BAD_DATA);
+ }
+
+ if (lifetime > 3600)
+ lifetime = 3600;
+
+ lifetime -= TURN_REFRESH_SLACK_SECONDS;
+
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Setting refresh timer for %u seconds",
+ tctx->label, lifetime);
+ NR_ASYNC_TIMER_SET(lifetime * 1000, nr_turn_client_refresh_timer_cb, sctx,
+ &tctx->refresh_timer_handle);
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_client_failed(tctx);
+ }
+ return _status;
+}
+
+static void nr_turn_client_refresh_timer_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+ int r,_status;
+
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Refresh timer fired",
+ ctx->tctx->label);
+
+ ctx->tctx->refresh_timer_handle=0;
+ if ((r=nr_turn_stun_ctx_start(ctx))) {
+ ABORT(r);
+ }
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_client_failed(ctx->tctx);
+ }
+ return;
+}
+
+static void nr_turn_client_refresh_cb(NR_SOCKET s, int how, void *arg)
+{
+ int r, _status;
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+ /* Save lifetime from the reset */
+ UINT4 lifetime = ctx->stun->results.refresh_response.lifetime_secs;
+
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Refresh succeeded. lifetime=%u",
+ ctx->tctx->label, lifetime);
+
+ if ((r=nr_turn_client_start_refresh_timer(
+ ctx->tctx, ctx, lifetime)))
+ ABORT(r);
+
+ _status=0;
+
+abort:
+ if (_status) {
+ nr_turn_client_failed(ctx->tctx);
+ }
+}
+
+/* TODO(ekr@rtfm.com): We currently don't support channels.
+ We might in the future. Mozilla bug 857736 */
+int nr_turn_client_send_indication(nr_turn_client_ctx *ctx,
+ const UCHAR *msg, size_t len,
+ int flags, nr_transport_addr *remote_addr)
+{
+ int r,_status;
+ nr_stun_client_send_indication_params params = { { 0 } };
+ nr_stun_message *ind = 0;
+
+ if (ctx->state != NR_TURN_CLIENT_STATE_ALLOCATED)
+ ABORT(R_FAILED);
+
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Send indication len=%zu",
+ ctx->label, len);
+
+ if ((r=nr_turn_client_ensure_perm(ctx, remote_addr)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(&params.remote_addr, remote_addr)))
+ ABORT(r);
+
+ params.data.data = (UCHAR*)msg;
+ params.data.len = len;
+
+ if ((r=nr_stun_build_send_indication(&params, &ind)))
+ ABORT(r);
+
+ if ((r=nr_turn_client_send_stun_request(ctx, ind, flags)))
+ ABORT(r);
+
+ _status=0;
+abort:
+ nr_stun_message_destroy(&ind);
+ return(_status);
+}
+
+int nr_turn_client_parse_data_indication(nr_turn_client_ctx *ctx,
+ nr_transport_addr *source_addr,
+ UCHAR *msg, size_t len,
+ UCHAR *newmsg, size_t *newlen,
+ size_t newsize,
+ nr_transport_addr *remote_addr)
+{
+ int r,_status;
+ nr_stun_message *ind=0;
+ nr_stun_message_attribute *attr;
+ nr_turn_permission *perm;
+
+ if (nr_transport_addr_cmp(&ctx->turn_server_addr, source_addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
+ r_log(NR_LOG_TURN, LOG_WARNING,
+ "TURN(%s): Indication from unexpected source addr %s (expected %s)",
+ ctx->label, source_addr->as_string, ctx->turn_server_addr.as_string);
+ ABORT(R_REJECTED);
+ }
+
+ if ((r=nr_stun_message_create2(&ind, msg, len)))
+ ABORT(r);
+ if ((r=nr_stun_decode_message(ind, 0, 0)))
+ ABORT(r);
+
+ if (ind->header.type != NR_STUN_MSG_DATA_INDICATION)
+ ABORT(R_BAD_ARGS);
+
+ if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_XOR_PEER_ADDRESS, &attr))
+ ABORT(R_BAD_ARGS);
+
+ if ((r=nr_turn_permission_find(ctx, &attr->u.xor_mapped_address.unmasked,
+ &perm))) {
+ if (r == R_NOT_FOUND) {
+ r_log(NR_LOG_TURN, LOG_WARNING,
+ "TURN(%s): Indication from peer addr %s with no permission",
+ ctx->label, attr->u.xor_mapped_address.unmasked.as_string);
+ }
+ ABORT(r);
+ }
+
+ if ((r=nr_transport_addr_copy(remote_addr,
+ &attr->u.xor_mapped_address.unmasked)))
+ ABORT(r);
+
+#if REFRESH_RESERVATION_ON_RECV
+ if ((r=nr_turn_client_ensure_perm(ctx, remote_addr))) {
+ ABORT(r);
+ }
+#endif
+
+ if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_DATA, &attr)) {
+ ABORT(R_BAD_DATA);
+ }
+
+ assert(newsize >= attr->u.data.length);
+ if (newsize < attr->u.data.length)
+ ABORT(R_BAD_ARGS);
+
+ memcpy(newmsg, attr->u.data.data, attr->u.data.length);
+ *newlen = attr->u.data.length;
+
+ _status=0;
+abort:
+ nr_stun_message_destroy(&ind);
+ return(_status);
+}
+
+
+
+/* The permissions model is as follows:
+
+ - We keep a list of all the permissions we have ever requested
+ along with when they were last established.
+ - Whenever someone sends a packet, we automatically create/
+ refresh the permission.
+
+ This means that permissions automatically time out if
+ unused.
+
+*/
+int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx, nr_transport_addr *addr)
+{
+ int r, _status;
+ nr_turn_permission *perm = 0;
+ UINT8 now;
+ UINT8 turn_permission_refresh = (TURN_PERMISSION_LIFETIME_SECONDS -
+ TURN_REFRESH_SLACK_SECONDS) * TURN_USECS_PER_S;
+
+ if ((r=nr_turn_permission_find(ctx, addr, &perm))) {
+ if (r == R_NOT_FOUND) {
+ if ((r=nr_turn_permission_create(ctx, addr, &perm)))
+ ABORT(r);
+ }
+ else {
+ ABORT(r);
+ }
+ }
+
+ assert(perm);
+
+ /* Now check that the permission is up-to-date */
+ now = r_gettimeint();
+
+ if ((now - perm->last_used) > turn_permission_refresh) {
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Permission for %s requires refresh",
+ ctx->label, perm->addr.as_string);
+
+ if ((r=nr_turn_stun_ctx_start(perm->stun)))
+ ABORT(r);
+
+ perm->last_used = now; /* Update the time now so we don't retry on
+ next packet */
+ }
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static int nr_turn_permission_create(nr_turn_client_ctx *ctx, nr_transport_addr *addr,
+ nr_turn_permission **permp)
+{
+ int r, _status;
+ nr_turn_permission *perm = 0;
+
+ assert(ctx->state == NR_TURN_CLIENT_STATE_ALLOCATED);
+
+ r_log(NR_LOG_TURN, LOG_INFO, "TURN(%s): Creating permission for %s",
+ ctx->label, addr->as_string);
+
+ if (!(perm = RCALLOC(sizeof(nr_turn_permission))))
+ ABORT(R_NO_MEMORY);
+
+ if ((r=nr_transport_addr_copy(&perm->addr, addr)))
+ ABORT(r);
+
+ perm->last_used = 0;
+
+ if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_PERMISSION_REQUEST,
+ nr_turn_client_permissions_cb,
+ nr_turn_client_permission_error_cb,
+ &perm->stun)))
+ ABORT(r);
+
+ /* We want to authenticate on the first packet */
+ if ((r=nr_turn_stun_set_auth_params(perm->stun, ctx->realm, ctx->nonce)))
+ ABORT(r);
+
+ if ((r=nr_transport_addr_copy(
+ &perm->stun->stun->params.permission_request.remote_addr, addr)))
+ ABORT(r);
+ STAILQ_INSERT_TAIL(&ctx->permissions, perm, entry);
+
+ *permp = perm;
+
+ _status=0;
+abort:
+ if (_status) {
+ nr_turn_permission_destroy(&perm);
+ }
+ return(_status);
+}
+
+
+static int nr_turn_permission_find(nr_turn_client_ctx *ctx, nr_transport_addr *addr,
+ nr_turn_permission **permp)
+{
+ nr_turn_permission *perm;
+ int _status;
+
+ perm = STAILQ_FIRST(&ctx->permissions);
+ while (perm) {
+ if (!nr_transport_addr_cmp(&perm->addr, addr,
+ NR_TRANSPORT_ADDR_CMP_MODE_ADDR))
+ break;
+
+ perm = STAILQ_NEXT(perm, entry);
+ }
+
+ if (!perm) {
+ ABORT(R_NOT_FOUND);
+ }
+ if (perm->stun->last_error_code == 403) {
+ ABORT(R_NOT_PERMITTED);
+ }
+ *permp = perm;
+
+ _status=0;
+abort:
+ return(_status);
+}
+
+static void nr_turn_client_permissions_cb(NR_SOCKET s, int how, void *arg)
+{
+ nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
+ r_log(NR_LOG_TURN, LOG_DEBUG, "TURN(%s): Successfully refreshed permission",
+ ctx->tctx->label);
+}
+
+/* Note that we don't destroy the nr_turn_stun_ctx. That is owned by the
+ nr_turn_client_ctx. */
+static int nr_turn_permission_destroy(nr_turn_permission **permp)
+{
+ nr_turn_permission *perm;
+
+ if (!permp || !*permp)
+ return(0);
+
+ perm = *permp;
+ *permp = 0;
+
+ RFREE(perm);
+
+ return(0);
+}
+
+#endif /* USE_TURN */
diff --git a/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.h b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.h
new file mode 100644
index 000000000..c50e79d3b
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.h
@@ -0,0 +1,137 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+Copyright (c) 2013, Mozilla
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance, Mozilla nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _turn_client_ctx_h
+#define _turn_client_ctx_h
+
+/*
+ Represents a single set of STUN transactions, i.e.,
+ Allocate, Refresh, Permission. It automatically handles
+ permissions and restarts.
+ */
+typedef struct nr_turn_stun_ctx_ {
+ struct nr_turn_client_ctx_ *tctx;
+ int mode; /* From stun_client_ctx.h, NR_TURN_CLIENT_MODE_* */
+ int retry_ct;
+ nr_stun_client_ctx *stun;
+ char *nonce;
+ char *realm;
+ NR_async_cb success_cb;
+ NR_async_cb error_cb;
+ int last_error_code;
+
+ STAILQ_ENTRY(nr_turn_stun_ctx_) entry;
+} nr_turn_stun_ctx;
+typedef STAILQ_HEAD(nr_turn_stun_ctx_head_, nr_turn_stun_ctx_)
+ nr_turn_stun_ctx_head;
+
+/* Represents a single TURN permission */
+typedef struct nr_turn_permission_ {
+ nr_transport_addr addr;
+ nr_turn_stun_ctx *stun;
+ UINT8 last_used;
+
+ STAILQ_ENTRY(nr_turn_permission_) entry;
+} nr_turn_permission;
+typedef STAILQ_HEAD(nr_turn_permission_head_, nr_turn_permission_)
+ nr_turn_permission_head;
+
+/* A single connection to a TURN server. Use one
+ turn_client_ctx per socket/server pair. */
+typedef struct nr_turn_client_ctx_ {
+ int state;
+#define NR_TURN_CLIENT_STATE_INITTED 1
+#define NR_TURN_CLIENT_STATE_ALLOCATING 2
+#define NR_TURN_CLIENT_STATE_ALLOCATED 3
+#define NR_TURN_CLIENT_STATE_FAILED 4
+#define NR_TURN_CLIENT_STATE_CANCELLED 5
+#define NR_TURN_CLIENT_STATE_DEALLOCATING 6
+
+ char *label;
+ nr_socket *sock;
+
+ char *username;
+ Data *password;
+ char *nonce;
+ char *realm;
+
+ nr_transport_addr turn_server_addr;
+ nr_transport_addr relay_addr;
+ nr_transport_addr mapped_addr;
+
+ nr_turn_stun_ctx_head stun_ctxs;
+ nr_turn_permission_head permissions;
+
+ NR_async_cb finished_cb;
+ void *cb_arg;
+
+ void *connected_timer_handle;
+ void *refresh_timer_handle;
+} nr_turn_client_ctx;
+
+extern int NR_LOG_TURN;
+
+int nr_turn_client_ctx_create(const char *label, nr_socket *sock,
+ const char *username, Data *password,
+ nr_transport_addr *addr,
+ nr_turn_client_ctx **ctxp);
+int nr_turn_client_ctx_destroy(nr_turn_client_ctx **ctxp);
+int nr_turn_client_allocate(nr_turn_client_ctx *ctx,
+ NR_async_cb finished_cb, void *cb_arg);
+int nr_turn_client_get_relayed_address(nr_turn_client_ctx *ctx,
+ nr_transport_addr *relayed_address);
+int nr_turn_client_get_mapped_address(nr_turn_client_ctx *ctx,
+ nr_transport_addr *mapped_address);
+int nr_turn_client_process_response(nr_turn_client_ctx *ctx,
+ UCHAR *msg, int len,
+ nr_transport_addr *turn_server_addr);
+int nr_turn_client_cancel(nr_turn_client_ctx *ctx);
+int nr_turn_client_failed(nr_turn_client_ctx *ctx);
+int nr_turn_client_deallocate(nr_turn_client_ctx *ctx);
+int nr_turn_client_send_indication(nr_turn_client_ctx *ctx,
+ const UCHAR *msg, size_t len,
+ int flags, nr_transport_addr *remote_addr);
+int nr_turn_client_parse_data_indication(nr_turn_client_ctx *ctx,
+ nr_transport_addr *source_addr,
+ UCHAR *msg, size_t len,
+ UCHAR *newmsg, size_t *newlen,
+ size_t newsize,
+ nr_transport_addr *remote_addr);
+int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx,
+ nr_transport_addr *addr);
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/util/cb_args.c b/media/mtransport/third_party/nICEr/src/util/cb_args.c
new file mode 100644
index 000000000..964f1abee
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/cb_args.c
@@ -0,0 +1,61 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+static char *RCSSTRING __UNUSED__="$Id: cb_args.c,v 1.2 2008/04/28 17:59:04 ekr Exp $";
+
+#include <stdarg.h>
+#include "nr_api.h"
+#include "cb_args.h"
+
+void **nr_pack_cb_args(int ct,...)
+ {
+ void **vlist;
+ va_list ap;
+ int i;
+
+ va_start(ap,ct);
+ if(!(vlist=RCALLOC(sizeof(void *)*ct+1)))
+ abort();
+
+ for(i=0;i<ct;i++){
+ vlist[i]=va_arg(ap, void *);
+ }
+
+ va_end(ap);
+
+ return(vlist);
+ }
+
+
+
diff --git a/media/mtransport/third_party/nICEr/src/util/cb_args.h b/media/mtransport/third_party/nICEr/src/util/cb_args.h
new file mode 100644
index 000000000..83f7831cc
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/cb_args.h
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _cb_args_h
+#define _cb_args_h
+
+void **nr_pack_cb_args(int ct,...);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/util/ice_util.c b/media/mtransport/third_party/nICEr/src/util/ice_util.c
new file mode 100644
index 000000000..047be6659
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/ice_util.c
@@ -0,0 +1,76 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdarg.h>
+
+
+static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
+
+#include <stdarg.h>
+#include <string.h>
+#include "nr_api.h"
+#include "ice_util.h"
+
+int nr_concat_strings(char **outp,...)
+ {
+ va_list ap;
+ char *s,*out=0;
+ int len=0;
+ int _status;
+
+ va_start(ap,outp);
+ while(s=va_arg(ap,char *)){
+ len+=strlen(s);
+ }
+ va_end(ap);
+
+
+ if(!(out=RMALLOC(len+1)))
+ ABORT(R_NO_MEMORY);
+
+ *outp=out;
+
+ va_start(ap,outp);
+ while(s=va_arg(ap,char *)){
+ len=strlen(s);
+ memcpy(out,s,len);
+ out+=len;
+ }
+ va_end(ap);
+
+ *out=0;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
diff --git a/media/mtransport/third_party/nICEr/src/util/ice_util.h b/media/mtransport/third_party/nICEr/src/util/ice_util.h
new file mode 100644
index 000000000..44751edaf
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/ice_util.h
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _ice_util_h
+#define _ice_util_h
+
+int nr_concat_strings(char **outp,...);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/src/util/mbslen.c b/media/mtransport/third_party/nICEr/src/util/mbslen.c
new file mode 100644
index 000000000..3645c95cf
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/mbslen.c
@@ -0,0 +1,139 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifdef LINUX
+#define _GNU_SOURCE 1
+#endif
+#include <string.h>
+
+#include <errno.h>
+#include <csi_platform.h>
+
+#include <assert.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <wchar.h>
+#if defined(DARWIN) || defined(__DragonFly__) || defined(__FreeBSD__)
+#define HAVE_XLOCALE
+#endif
+
+#ifdef HAVE_XLOCALE
+#include <xlocale.h>
+#endif /* HAVE_XLOCALE */
+
+#include "nr_api.h"
+#include "mbslen.h"
+
+/* get number of characters in a mult-byte character string */
+int
+mbslen(const char *s, size_t *ncharsp)
+{
+#ifdef HAVE_XLOCALE
+ static locale_t loc = 0;
+ static int initialized = 0;
+#endif /* HAVE_XLOCALE */
+#ifdef WIN32
+ char *my_locale=0;
+ unsigned int i;
+#endif /* WIN32 */
+ int _status;
+ size_t nbytes;
+ int nchars;
+ mbstate_t mbs;
+
+#ifdef HAVE_XLOCALE
+ if (! initialized) {
+ initialized = 1;
+ loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
+ }
+
+ if (loc == 0) {
+ /* unable to create the UTF-8 locale */
+ assert(loc != 0); /* should never happen */
+#endif /* HAVE_XLOCALE */
+
+#ifdef WIN32
+ if (!setlocale(LC_CTYPE, 0))
+ ABORT(R_INTERNAL);
+
+ if (!(my_locale = r_strdup(setlocale(LC_CTYPE, 0))))
+ ABORT(R_NO_MEMORY);
+
+ for (i=0; i<strlen(my_locale); i++)
+ my_locale[i] = toupper(my_locale[i]);
+
+ if (!strstr(my_locale, "UTF-8") && !strstr(my_locale, "UTF8"))
+ ABORT(R_NOT_FOUND);
+#else
+ /* can't count UTF-8 characters with mbrlen if the locale isn't UTF-8 */
+ /* null-checking setlocale is required because Android */
+ char *locale = setlocale(LC_CTYPE, 0);
+ /* some systems use "utf8" instead of "UTF-8" like Fedora 17 */
+ if (!locale || (!strcasestr(locale, "UTF-8") && !strcasestr(locale, "UTF8")))
+ ABORT(R_NOT_FOUND);
+#endif
+
+#ifdef HAVE_XLOCALE
+ }
+#endif /* HAVE_XLOCALE */
+
+ memset(&mbs, 0, sizeof(mbs));
+ nchars = 0;
+
+#ifdef HAVE_XLOCALE
+ while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
+#else
+ while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
+#endif /* HAVE_XLOCALE */
+ {
+ if (nbytes == (size_t)-1) /* should never happen */ {
+ ABORT(R_INTERNAL);
+ }
+ if (nbytes == (size_t)-2) /* encoding error */ {
+ ABORT(R_BAD_DATA);
+ }
+
+ s += nbytes;
+ ++nchars;
+ }
+
+ *ncharsp = nchars;
+
+ _status = 0;
+ abort:
+#ifdef WIN32
+ RFREE(my_locale);
+#endif
+ return _status;
+}
+
diff --git a/media/mtransport/third_party/nICEr/src/util/mbslen.h b/media/mtransport/third_party/nICEr/src/util/mbslen.h
new file mode 100644
index 000000000..9a68e5dae
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/src/util/mbslen.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#ifndef _mbslen_h
+#define _mbslen_h
+
+/* get number of characters in a mult-byte character string */
+int mbslen(const char *s, size_t *ncharsp);
+
+#endif
+
diff --git a/media/mtransport/third_party/nICEr/upstream.diff b/media/mtransport/third_party/nICEr/upstream.diff
new file mode 100644
index 000000000..a664fd9d2
--- /dev/null
+++ b/media/mtransport/third_party/nICEr/upstream.diff
@@ -0,0 +1,2449 @@
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c src/ice/ice_candidate.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_candidate.c 2012-10-06 08:30:22.000000000 -0700
+@@ -54,36 +54,38 @@
+
+ #include "stun_client_ctx.h"
+ #include "stun_server_ctx.h"
+ #include "turn_client_ctx.h"
+ #include "ice_ctx.h"
+ #include "ice_candidate.h"
+ #include "ice_reg.h"
+ #include "ice_util.h"
+ #include "nr_socket_turn.h"
+
++static int next_automatic_preference = 224;
++
+ static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
+ static int nr_ice_srvrflx_start_stun(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
+-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg);
++static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg);
+ #ifdef USE_TURN
+ static int nr_ice_start_relay_turn(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
+-static void nr_ice_turn_allocated_cb(int sock, int how, void *cb_arg);
++static void nr_ice_turn_allocated_cb(NR_SOCKET sock, int how, void *cb_arg);
+ #endif /* USE_TURN */
+
+ char *nr_ice_candidate_type_names[]={0,"host","srflx","prflx","relay",0};
+
+ int nr_ice_candidate_create(nr_ice_ctx *ctx,char *label,nr_ice_component *comp,nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp)
+ {
+ nr_ice_candidate *cand=0;
+ nr_ice_candidate *tmp=0;
+ int r,_status;
+-
++
+ if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
+ ABORT(R_NO_MEMORY);
+ if(!(cand->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+ cand->state=NR_ICE_CAND_STATE_CREATED;
+ cand->ctx=ctx;
+ cand->isock=isock;
+ cand->osock=osock;
+ cand->type=ctype;
+ cand->stun_server=stun_server;
+@@ -189,21 +191,21 @@
+ if(cand->delay_timer)
+ NR_async_timer_cancel(cand->delay_timer);
+
+ RFREE(cand->foundation);
+ RFREE(cand->label);
+ RFREE(cand);
+
+ return(0);
+ }
+
+-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg)
++void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ nr_ice_candidate_destroy(&cand);
+ }
+
+ /* This algorithm is not super-fast, but I don't think we need a hash
+ table just yet and it produces a small foundation string */
+ static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand)
+ {
+ nr_ice_foundation *foundation;
+@@ -276,22 +278,38 @@
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ }
+
+ if(type_preference > 126)
+ r_log(LOG_ICE,LOG_ERR,"Illegal type preference %d",type_preference);
+
+
+ if(r=NR_reg_get2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,
+- &interface_preference))
+- ABORT(r);
++ &interface_preference)) {
++ if (r==R_NOT_FOUND) {
++ if (next_automatic_preference == 1) {
++ r_log(LOG_ICE,LOG_DEBUG,"Out of preference values. Can't assign one for interface %s",cand->base.ifname);
++ ABORT(R_NOT_FOUND);
++ }
++ r_log(LOG_ICE,LOG_DEBUG,"Automatically assigning preference for interface %s->%d",cand->base.ifname,
++ next_automatic_preference);
++ if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
++ ABORT(r);
++ }
++ interface_preference=next_automatic_preference;
++ next_automatic_preference--;
++ }
++ else {
++ ABORT(r);
++ }
++ }
+
+ cand->priority=
+ (type_preference << 24) |
+ (interface_preference << 16) |
+ (stun_priority << 8) |
+ (256 - cand->component_id);
+
+ /* S 4.1.2 */
+ assert(cand->priority>=1&&cand->priority<=2147483647);
+
+@@ -306,21 +324,22 @@
+
+ cand->done_cb=ready_cb;
+ cand->cb_arg=cb_arg;
+
+ switch(cand->type){
+ case HOST:
+ if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
+ ABORT(r);
+ cand->osock=cand->isock->sock;
+ cand->state=NR_ICE_CAND_STATE_INITIALIZED;
+- ready_cb(0,0,cb_arg);
++ // Post this so that it doesn't happen in-line
++ NR_ASYNC_SCHEDULE(ready_cb,cb_arg);
+ break;
+ #ifdef USE_TURN
+ case RELAYED:
+ if(r=nr_ice_start_relay_turn(cand,ready_cb,cb_arg))
+ ABORT(r);
+ ABORT(R_WOULDBLOCK);
+ break;
+ #endif /* USE_TURN */
+ case SERVER_REFLEXIVE:
+ /* Need to start stun */
+@@ -333,21 +352,21 @@
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+ abort:
+ if(_status && _status!=R_WOULDBLOCK)
+ cand->state=NR_ICE_CAND_STATE_FAILED;
+ return(_status);
+ }
+
+-static void nr_ice_srvrflx_start_stun_timer_cb(int s, int how, void *cb_arg)
++static void nr_ice_srvrflx_start_stun_timer_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ int r,_status;
+
+ cand->delay_timer=0;
+
+ /* TODO: if the response is a BINDING-ERROR-RESPONSE, then restart
+ * TODO: using NR_STUN_CLIENT_MODE_BINDING_REQUEST because the
+ * TODO: server may not have understood the 0.96-style request */
+ if(r=nr_stun_client_start(cand->u.srvrflx.stun, NR_STUN_CLIENT_MODE_BINDING_REQUEST_STUND_0_96, nr_ice_srvrflx_stun_finished_cb, cand))
+@@ -387,21 +406,21 @@
+
+ _status=0;
+ abort:
+ if(_status){
+ cand->state=NR_ICE_CAND_STATE_FAILED;
+ }
+ return(_status);
+ }
+
+ #ifdef USE_TURN
+-static void nr_ice_start_relay_turn_timer_cb(int s, int how, void *cb_arg)
++static void nr_ice_start_relay_turn_timer_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_candidate *cand=cb_arg;
+ int r,_status;
+ int i;
+
+ cand->delay_timer=0;
+
+ if(r=nr_turn_client_allocate(cand->u.relayed.turn, cand->u.relayed.server->username, cand->u.relayed.server->password, cand->u.relayed.server->bandwidth_kbps, cand->u.relayed.server->lifetime_secs, nr_ice_turn_allocated_cb, cand))
+ ABORT(r);
+
+@@ -443,21 +462,21 @@
+
+ _status=0;
+ abort:
+ if(_status){
+ cand->state=NR_ICE_CAND_STATE_FAILED;
+ }
+ return(_status);
+ }
+ #endif /* USE_TURN */
+
+-static void nr_ice_srvrflx_stun_finished_cb(int sock, int how, void *cb_arg)
++static void nr_ice_srvrflx_stun_finished_cb(NR_SOCKET sock, int how, void *cb_arg)
+ {
+ int _status;
+ nr_ice_candidate *cand=cb_arg;
+
+ /* Deregister to suppress duplicates */
+ if(cand->u.srvrflx.stun_handle){ /* This test because we might have failed before CB registered */
+ nr_ice_socket_deregister(cand->isock,cand->u.srvrflx.stun_handle);
+ cand->u.srvrflx.stun_handle=0;
+ }
+
+@@ -481,40 +500,40 @@
+ }
+ _status = 0;
+ abort:
+ if(_status){
+ cand->state=NR_ICE_CAND_STATE_FAILED;
+ cand->done_cb(0,0,cand->cb_arg);
+ }
+ }
+
+ #ifdef USE_TURN
+-static void nr_ice_turn_allocated_cb(int s, int how, void *cb_arg)
++static void nr_ice_turn_allocated_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_candidate *cand=cb_arg;
+ nr_turn_client_ctx *turn=cand->u.relayed.turn;
+ int i;
+ char *label;
+
+ /* Deregister to suppress duplicates */
+ if(cand->u.relayed.turn_handle){ /* This test because we might have failed before CB registered */
+ nr_ice_socket_deregister(cand->isock,cand->u.relayed.turn_handle);
+ cand->u.relayed.turn_handle=0;
+ }
+
+ switch(turn->state){
+ /* OK, we should have a mapped address */
+ case NR_TURN_CLIENT_STATE_ALLOCATED:
+ /* switch candidate from TURN mode to STUN mode */
+
+- if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",0))
++ if(r=nr_concat_strings(&label,"turn-relay(",cand->base.as_string,"|",turn->relay_addr.as_string,")",NULL))
+ ABORT(r);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Switching from TURN (%s) to RELAY (%s)",cand->u.relayed.turn->label,cand->label,label);
+
+ /* Copy out mapped address and relay address */
+ nr_transport_addr_copy(&turn->relay_addr, &cand->u.relayed.turn->stun_ctx[NR_TURN_CLIENT_PHASE_ALLOCATE_REQUEST2]->results.allocate_response2.relay_addr);
+ nr_transport_addr_copy(&cand->addr, &turn->relay_addr);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-CANDIDATE(%s): base=%s, candidate=%s", cand->label, cand->base.as_string, cand->addr.as_string);
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h src/ice/ice_candidate.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate.h 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_candidate.h 2012-10-06 08:30:22.000000000 -0700
+@@ -41,21 +41,22 @@
+
+ typedef enum {HOST=1, SERVER_REFLEXIVE, PEER_REFLEXIVE, RELAYED} nr_ice_candidate_type;
+
+ struct nr_ice_candidate_ {
+ char *label;
+ int state;
+ #define NR_ICE_CAND_STATE_CREATED 1
+ #define NR_ICE_CAND_STATE_INITIALIZING 2
+ #define NR_ICE_CAND_STATE_INITIALIZED 3
+ #define NR_ICE_CAND_STATE_FAILED 4
+-#define NR_ICE_CAND_PEER_CANDIDATE 10
++#define NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED 9
++#define NR_ICE_CAND_PEER_CANDIDATE_PAIRED 10
+ struct nr_ice_ctx_ *ctx;
+ nr_ice_socket *isock; /* The socket to read from
+ (it contains all other candidates
+ on this socket) */
+ nr_socket *osock; /* The socket to write to */
+ nr_ice_media_stream *stream; /* The media stream this is associated with */
+ nr_ice_component *component; /* The component this is associated with */
+ nr_ice_candidate_type type; /* The type of the candidate (S 4.1.1) */
+ UCHAR component_id; /* The component id (S 4.1.2.1) */
+ nr_transport_addr addr; /* The advertised address;
+@@ -89,21 +90,21 @@
+ TAILQ_ENTRY(nr_ice_candidate_) entry_comp;
+ };
+
+ extern char *nr_ice_candidate_type_names[];
+
+
+ int nr_ice_candidate_create(struct nr_ice_ctx_ *ctx,char *label, nr_ice_component *component, nr_ice_socket *isock, nr_socket *osock, nr_ice_candidate_type ctype, nr_ice_stun_server *stun_server, UCHAR component_id, nr_ice_candidate **candp);
+ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg);
+ int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr);
+ int nr_ice_candidate_destroy(nr_ice_candidate **candp);
+-void nr_ice_candidate_destroy_cb(int s, int h, void *cb_arg);
++void nr_ice_candidate_destroy_cb(NR_SOCKET s, int h, void *cb_arg);
+ int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen);
+ int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp);
+ int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp);
+ int nr_ice_candidate_compute_priority(nr_ice_candidate *cand);
+
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #endif
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c src/ice/ice_candidate_pair.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_candidate_pair.c 2012-10-06 08:30:22.000000000 -0700
+@@ -37,21 +37,21 @@
+ #include <assert.h>
+ #include <string.h>
+ #include <nr_api.h>
+ #include "ice_ctx.h"
+ #include "ice_util.h"
+ #include "ice_codeword.h"
+ #include "stun.h"
+
+ static char *nr_ice_cand_pair_states[]={"UNKNOWN","FROZEN","WAITING","IN_PROGRESS","FAILED","SUCCEEDED","CANCELLED"};
+
+-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg);
++static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg);
+ static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
+ nr_ice_candidate *lcand, nr_ice_candidate *rcand);
+
+ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp)
+ {
+ nr_ice_cand_pair *pair=0;
+ UINT8 o_priority, a_priority;
+ char *lufrag,*rufrag;
+ char *lpwd,*rpwd;
+ char *l2ruser=0,*r2lpass=0;
+@@ -61,21 +61,21 @@
+ UINT8 t_priority;
+
+ if(!(pair=RCALLOC(sizeof(nr_ice_cand_pair))))
+ ABORT(R_NO_MEMORY);
+
+ pair->pctx=pctx;
+
+ nr_ice_candidate_pair_compute_codeword(pair,lcand,rcand);
+
+ if(r=nr_concat_strings(&pair->as_string,pair->codeword,"|",lcand->addr.as_string,"|",
+- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
++ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")", NULL))
+ ABORT(r);
+
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
+ pair->local=lcand;
+ pair->remote=rcand;
+
+ /* Priority computation S 5.7.2 */
+ if(pctx->ctx->flags & NR_ICE_CTX_FLAGS_OFFERER)
+ {
+ assert(!(pctx->ctx->flags & NR_ICE_CTX_FLAGS_ANSWERER));
+@@ -87,21 +87,21 @@
+ o_priority=rcand->priority;
+ a_priority=lcand->priority;
+ }
+ pair->priority=(MIN(o_priority, a_priority))<<32 |
+ (MAX(o_priority, a_priority))<<1 | (o_priority > a_priority?0:1);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Pairing candidate %s (%x):%s (%x) priority=%llu (%llx) codeword=%s",pctx->ctx->label,lcand->addr.as_string,lcand->priority,rcand->addr.as_string,rcand->priority,pair->priority,pair->priority,pair->codeword);
+
+ /* Foundation */
+ if(r=nr_concat_strings(&pair->foundation,lcand->foundation,"|",
+- rcand->foundation,0))
++ rcand->foundation,NULL))
+ ABORT(r);
+
+
+ /* OK, now the STUN data */
+ lufrag=lcand->stream->ufrag?lcand->stream->ufrag:pctx->ctx->ufrag;
+ lpwd=lcand->stream->pwd?lcand->stream->pwd:pctx->ctx->pwd;
+ rufrag=rcand->stream->ufrag?rcand->stream->ufrag:pctx->peer_ufrag;
+ rpwd=rcand->stream->pwd?rcand->stream->pwd:pctx->peer_pwd;
+
+
+@@ -110,39 +110,39 @@
+
+ /* Make a bogus candidate to compute a theoretical peer reflexive
+ * priority per S 7.1.1.1 */
+ memcpy(&tmpcand, lcand, sizeof(tmpcand));
+ tmpcand.type = PEER_REFLEXIVE;
+ if (r=nr_ice_candidate_compute_priority(&tmpcand))
+ ABORT(r);
+ t_priority = tmpcand.priority;
+
+ /* Our sending context */
+- if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,0))
++ if(r=nr_concat_strings(&l2ruser,lufrag,":",rufrag,NULL))
+ ABORT(r);
+ if(r=nr_stun_client_ctx_create(pair->as_string,
+ lcand->osock,
+ &rcand->addr,RTO,&pair->stun_client))
+ ABORT(r);
+ if(!(pair->stun_client->params.ice_binding_request.username=r_strdup(l2ruser)))
+ ABORT(R_NO_MEMORY);
+ if(r=r_data_make(&pair->stun_client->params.ice_binding_request.password,(UCHAR *)lpwd,strlen(lpwd)))
+ ABORT(r);
+ pair->stun_client->params.ice_binding_request.priority=t_priority;
+ pair->stun_client->params.ice_binding_request.control = pctx->controlling?
+ NR_ICE_CONTROLLING:NR_ICE_CONTROLLED;
+
+ pair->stun_client->params.ice_binding_request.tiebreaker=pctx->tiebreaker;
+
+ /* Our receiving username/passwords. Stash these for later
+ injection into the stun server ctx*/
+- if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,0))
++ if(r=nr_concat_strings(&pair->r2l_user,rufrag,":",lufrag,NULL))
+ ABORT(r);
+ if(!(r2lpass=r_strdup(rpwd)))
+ ABORT(R_NO_MEMORY);
+ INIT_DATA(pair->r2l_pwd,(UCHAR *)r2lpass,strlen(r2lpass));
+
+ *pairp=pair;
+
+ _status=0;
+ abort:
+ RFREE(l2ruser);
+@@ -178,21 +178,21 @@
+
+ int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
+ {
+ assert(pair->state==NR_ICE_PAIR_STATE_FROZEN);
+
+ nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_WAITING);
+
+ return(0);
+ }
+
+-static void nr_ice_candidate_pair_stun_cb(int s, int how, void *cb_arg)
++static void nr_ice_candidate_pair_stun_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_cand_pair *pair=cb_arg,*orig_pair;
+ nr_ice_candidate *cand=0;
+ nr_stun_message *sres;
+ nr_transport_addr *request_src;
+ nr_transport_addr *request_dst;
+ nr_transport_addr *response_src;
+ nr_transport_addr response_dst;
+ nr_stun_message_attribute *attr;
+@@ -457,32 +457,47 @@
+ abort:
+ return(_status);
+ }
+
+ int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state)
+ {
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): setting pair %s to %s",
+ pctx->label,pair->as_string,nr_ice_cand_pair_states[state]);
+- pair->state=state;
+
+- if(pctx->state!=NR_ICE_PAIR_STATE_WAITING){
++ /* NOTE: This function used to reference pctx->state instead of
++ pair->state and the assignment to pair->state was at the top
++ of this function. Because pctx->state was never changed, this seems to have
++ been a typo. The natural logic is "if the state changed
++ decrement the counter" so this implies we should be checking
++ the pair state rather than the pctx->state.
++
++ This didn't cause big problems because waiting_pairs was only
++ used for pacing, so the pacing just was kind of broken.
++
++ This note is here as a reminder until we do more testing
++ and make sure that in fact this was a typo.
++ */
++ if(pair->state!=NR_ICE_PAIR_STATE_WAITING){
+ if(state==NR_ICE_PAIR_STATE_WAITING)
+ pctx->waiting_pairs++;
+ }
+ else{
+ if(state!=NR_ICE_PAIR_STATE_WAITING)
+ pctx->waiting_pairs--;
+
+ assert(pctx->waiting_pairs>=0);
+ }
++ pair->state=state;
++
++
+ if(pair->state==NR_ICE_PAIR_STATE_FAILED){
+ if(r=nr_ice_component_failed_pair(pair->remote->component, pair))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+@@ -505,42 +520,42 @@
+ break;
+ }
+
+ c1=TAILQ_NEXT(c1,entry);
+ }
+ if(!c1) TAILQ_INSERT_TAIL(head,pair,entry);
+
+ return(0);
+ }
+
+-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg)
++void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_cand_pair *pair=cb_arg;
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as nominated",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
+
+ nr_stun_client_reset(pair->stun_client);
+ pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLING;
+
+ if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_USE_CANDIDATE,nr_ice_candidate_pair_stun_cb,pair))
+ ABORT(r);
+
+ if(r=nr_ice_ctx_remember_id(pair->pctx->ctx, pair->stun_client->request))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return;
+ }
+
+-static void nr_ice_candidate_pair_restart_stun_controlled_cb(int s, int how, void *cb_arg)
++static void nr_ice_candidate_pair_restart_stun_controlled_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_cand_pair *pair=cb_arg;
+ int r,_status;
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s):%d: Restarting pair %s as CONTROLLED",pair->pctx->label,pair->local->stream->label,pair->remote->component->component_id,pair->as_string);
+
+ nr_stun_client_reset(pair->stun_client);
+ pair->stun_client->params.ice_binding_request.control=NR_ICE_CONTROLLED;
+
+ if(r=nr_stun_client_start(pair->stun_client,NR_ICE_CLIENT_MODE_BINDING_REQUEST,nr_ice_candidate_pair_stun_cb,pair))
+@@ -556,21 +571,21 @@
+
+
+
+ static void nr_ice_candidate_pair_compute_codeword(nr_ice_cand_pair *pair,
+ nr_ice_candidate *lcand, nr_ice_candidate *rcand)
+ {
+ int r,_status;
+ char *as_string=0;
+
+ if(r=nr_concat_strings(&as_string,lcand->addr.as_string,"|",
+- rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",0))
++ rcand->addr.as_string,"(",lcand->label,"|",rcand->label,")",NULL))
+ ABORT(r);
+
+ nr_ice_compute_codeword(as_string,strlen(as_string),pair->codeword);
+
+ _status=0;
+ abort:
+ RFREE(as_string);
+ return;
+ }
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h src/ice/ice_candidate_pair.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_candidate_pair.h 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_candidate_pair.h 2012-10-06 08:30:22.000000000 -0700
+@@ -72,18 +72,18 @@
+
+ int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp);
+ int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+ int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+ int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state);
+ int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out);
+ int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair);
+ int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair);
+ int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair);
+ int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair);
+-void nr_ice_candidate_pair_restart_stun_nominated_cb(int s, int how, void *cb_arg);
++void nr_ice_candidate_pair_restart_stun_nominated_cb(NR_SOCKET s, int how, void *cb_arg);
+ int nr_ice_candidate_pair_destroy(nr_ice_cand_pair **pairp);
+
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #endif
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c src/ice/ice_component.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_component.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_component.c 2012-10-06 08:30:22.000000000 -0700
+@@ -451,21 +451,21 @@
+ if(r=nr_ice_peer_peer_rflx_candidate_create(comp->stream->pctx->ctx,"prflx",comp,&req->src_addr,&pcand)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+ if(!nr_stun_message_has_attribute(sreq,NR_STUN_ATTR_PRIORITY,&attr)){
+ r_log(LOG_ICE,LOG_ERR,"ICE-PEER(%s): Rejecting stun request without priority",comp->stream->pctx->label);
+ *error=487;
+ ABORT(R_BAD_DATA);
+ }
+ pcand->priority=attr->u.priority;
+- pcand->state=NR_ICE_CAND_PEER_CANDIDATE;
++ pcand->state=NR_ICE_CAND_PEER_CANDIDATE_PAIRED;;
+ TAILQ_INSERT_TAIL(&comp->candidates,pcand,entry_comp);
+
+ if(r=nr_ice_candidate_pair_create(comp->stream->pctx,cand,pcand,
+ &pair)) {
+ *error=(r==R_NO_MEMORY)?500:400;
+ ABORT(r);
+ }
+ nr_ice_candidate_pair_set_state(pair->pctx,pair,NR_ICE_PAIR_STATE_FROZEN);
+
+ if(r=nr_ice_candidate_pair_insert(&comp->stream->check_list,pair)) {
+@@ -563,30 +563,38 @@
+ break;
+ }
+
+ /* PAIR with each peer*/
+ if(TAILQ_EMPTY(&pcomp->candidates)) {
+ /* can happen if our peer proposes no (or all bogus) candidates */
+ goto next_cand;
+ }
+ pcand=TAILQ_FIRST(&pcomp->candidates);
+ while(pcand){
+- nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
+- r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
+-
+- if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
+- ABORT(r);
+-
+- if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
+- pair))
+- ABORT(r);
++ /* Only pair peer candidates which have not yet been paired.
++ This allows "trickle ICE". (Not yet standardized, but
++ part of WebRTC).
++
++ TODO(ekr@rtfm.com): Add refernece to the spec when there
++ is one.
++ */
++ if (pcand->state = NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED) {
++ nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
++ r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
++
++ if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
++ ABORT(r);
+
++ if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
++ pair))
++ ABORT(r);
++ }
+ pcand=TAILQ_NEXT(pcand,entry_comp);
+ }
+
+ if(!pair)
+ ABORT(R_INTERNAL);
+
+ /* Add the stun username/password pair from the last pair (any
+ would do) to the stun contexts */
+ isock=STAILQ_FIRST(&lcomp->sockets);
+ while(isock){
+@@ -594,20 +602,28 @@
+ pair->r2l_user,&pair->r2l_pwd,nr_ice_component_stun_server_cb,pcomp))
+ ABORT(r);
+
+ isock=STAILQ_NEXT(isock,entry);
+ }
+
+ next_cand:
+ lcand=TAILQ_NEXT(lcand,entry_comp);
+ }
+
++ /* Mark all peer candidates as paired */
++ pcand=TAILQ_FIRST(&pcomp->candidates);
++ while(pcand){
++ pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
++
++ pcand=TAILQ_NEXT(pcand,entry_comp);
++ }
++
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+ int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair)
+ {
+ int r,_status;
+ int fire_cb=0;
+ nr_ice_cand_pair *p2;
+@@ -616,32 +632,32 @@
+ fire_cb=1;
+
+ /* Are we changing what the nominated pair is? */
+ if(comp->nominated){
+ if(comp->nominated->priority > pair->priority)
+ return(0);
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): replacing pair %s with pair %s",comp->stream->pctx->label,comp->stream->label,comp->component_id,comp->nominated->as_string,pair->as_string);
+ }
+
+ /* Set the new nominated pair */
+- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): nominated pair is %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
+ comp->state=NR_ICE_COMPONENT_NOMINATED;
+ comp->nominated=pair;
+ comp->active=pair;
+
+- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,(int)pair);
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling all pairs but %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,pair->as_string,pair);
+
+ /* OK, we need to cancel off everything on this component */
+ p2=TAILQ_FIRST(&comp->stream->check_list);
+ while(p2){
+ if((p2 != pair) && (p2->remote->component->component_id == comp->component_id)){
+- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%x)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,(int)p2);
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling pair %s (0x%p)",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->as_string,p2);
+
+ if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2))
+ ABORT(r);
+ }
+
+ p2=TAILQ_NEXT(p2,entry);
+ }
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/STREAM(%s)/comp(%d): cancelling done",comp->stream->pctx->label,comp->stream->label,comp->component_id);
+
+ if(r=nr_ice_media_stream_component_nominated(comp->stream,comp))
+@@ -734,21 +750,21 @@
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ RFREE(pairs);
+ return(_status);
+ }
+
+
+-static void nr_ice_component_keepalive_cb(int s, int how, void *cb_arg)
++static void nr_ice_component_keepalive_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_component *comp=cb_arg;
+ UINT4 keepalive_timeout;
+
+ assert(comp->keepalive_ctx);
+
+ if(NR_reg_get_uint4(NR_ICE_REG_KEEPALIVE_TIMER,&keepalive_timeout)){
+ keepalive_timeout=15000; /* Default */
+ }
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c src/ice/ice_ctx.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_ctx.c 2012-10-06 08:30:22.000000000 -0700
+@@ -56,21 +56,21 @@
+ #include "util.h"
+
+
+ int LOG_ICE = 0;
+
+ static int nr_ice_random_string(char *str, int len);
+ static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
+ #ifdef USE_TURN
+ static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
+ #endif /* USE_TURN */
+-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg);
++static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
+
+ int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
+ {
+ int r,_status;
+ nr_ice_stun_server *servers = 0;
+ int i;
+ NR_registry child;
+ char *addr=0;
+ UINT2 port;
+ in_addr_t addr_int;
+@@ -271,21 +271,21 @@
+ *ctxp=ctx;
+
+ _status=0;
+ abort:
+ if(_status)
+ nr_ice_ctx_destroy_cb(0,0,ctx);
+
+ return(_status);
+ }
+
+-static void nr_ice_ctx_destroy_cb(int s, int how, void *cb_arg)
++static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_ctx *ctx=cb_arg;
+ nr_ice_foundation *f1,*f2;
+ nr_ice_media_stream *s1,*s2;
+ int i;
+ nr_ice_stun_id *id1,*id2;
+
+ RFREE(ctx->label);
+
+ RFREE(ctx->stun_servers);
+@@ -323,21 +323,21 @@
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
+
+ *ctxp=0;
+
+ return(0);
+ }
+
+-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg)
++void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
+ {
+ nr_ice_ctx *ctx=cb_arg;
+
+ /* r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Candidate %s %s",ctx->label,
+ cand->label, cand->state==NR_ICE_CAND_STATE_INITIALIZED?"INITIALIZED":"FAILED");
+ */
+ ctx->uninitialized_candidates--;
+
+ if(ctx->uninitialized_candidates==0){
+ r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
+@@ -368,21 +368,22 @@
+ stream=STAILQ_FIRST(&ctx->streams);
+ while(stream){
+ if(r=nr_ice_media_stream_initialize(ctx,stream))
+ ABORT(r);
+
+ stream=STAILQ_NEXT(stream,entry);
+ }
+
+ if(ctx->uninitialized_candidates)
+ ABORT(R_WOULDBLOCK);
+-
++
++
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+ int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
+ {
+ int r,_status;
+
+ if(r=nr_ice_media_stream_create(ctx,label,components,streamp))
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h src/ice/ice_ctx.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_ctx.h 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_ctx.h 2012-10-06 08:30:22.000000000 -0700
+@@ -92,23 +92,23 @@
+ UCHAR id[12];
+
+ STAILQ_ENTRY(nr_ice_stun_id_) entry;
+ } nr_ice_stun_id;
+
+ typedef STAILQ_HEAD(nr_ice_stun_id_head_,nr_ice_stun_id_) nr_ice_stun_id_head;
+
+ struct nr_ice_ctx_ {
+ UINT4 flags;
+ int state;
+-#define NR_ICE_STATE_CREATED 1
+-#define NR_ICE_STATE_INITIALIZING 2
+-#define NR_ICE_STATE_INITIALIZED 3
++#define NR_ICE_STATE_CREATED 1
++#define NR_ICE_STATE_INITIALIZING 2
++#define NR_ICE_STATE_INITIALIZED 3
+ char *label;
+
+ char *ufrag;
+ char *pwd;
+
+ UINT4 Ta;
+
+ nr_ice_stun_server *stun_servers; /* The list of stun servers */
+ int stun_server_ct;
+ nr_ice_turn_server *turn_servers; /* The list of turn servers */
+@@ -133,21 +133,21 @@
+
+ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
+ #define NR_ICE_CTX_FLAGS_OFFERER 1
+ #define NR_ICE_CTX_FLAGS_ANSWERER (1<<1)
+ #define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1<<2)
+ #define NR_ICE_CTX_FLAGS_LITE (1<<3)
+
+ int nr_ice_ctx_destroy(nr_ice_ctx **ctxp);
+ int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
+ int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
+-void nr_ice_initialize_finished_cb(int s, int h, void *cb_arg);
++void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg);
+ int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp);
+ int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp);
+ int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
+ int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
+ int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
+ int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
+
+ extern int LOG_ICE;
+
+ #ifdef __cplusplus
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c src/ice/ice_media_stream.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_media_stream.c 2012-10-06 08:30:22.000000000 -0700
+@@ -35,21 +35,21 @@
+ static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+ #include <string.h>
+ #include <assert.h>
+ #include <nr_api.h>
+ #include <r_assoc.h>
+ #include <async_timer.h>
+ #include "ice_ctx.h"
+
+ static char *nr_ice_media_stream_states[]={"INVALID",
+- "FROZEN","ACTIVE","COMPLETED","FAILED"
++ "UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
+ };
+
+ int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
+
+ int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream=0;
+ nr_ice_component *comp=0;
+ int i;
+@@ -66,29 +66,29 @@
+ for(i=0;i<components;i++){
+ /* component-id must be > 0, so increment by 1 */
+ if(r=nr_ice_component_create(stream, i+1, &comp))
+ ABORT(r);
+
+ }
+
+ TAILQ_INIT(&stream->check_list);
+
+ stream->component_ct=components;
+-
++ stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
+ *streamp=stream;
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_ice_media_stream_destroy(&stream);
+ }
+- return(_status);
++ return(_status);
+ }
+
+ int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp)
+ {
+ nr_ice_media_stream *stream;
+ nr_ice_component *c1,*c2;
+ nr_ice_cand_pair *p1,*p2;
+ if(!streamp || !*streamp)
+ return(0);
+
+@@ -200,85 +200,148 @@
+ if(attrs){
+ for(index=0;index<attrct;index++){
+ RFREE(attrs[index]);
+ }
+ RFREE(attrs);
+ }
+ }
+ return(_status);
+ }
+
++
++/* Get a default candidate per 4.1.4 */
++int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp)
++ {
++ int _status;
++ nr_ice_component *comp;
++ nr_ice_candidate *cand;
++ nr_ice_candidate *best_cand = NULL;
++
++ comp=STAILQ_FIRST(&stream->components);
++ while(comp){
++ if (comp->component_id == component)
++ break;
++
++ comp=STAILQ_NEXT(comp,entry);
++ }
++
++ if (!comp)
++ ABORT(R_NOT_FOUND);
++
++ /* We have the component. Now find the "best" candidate, making
++ use of the fact that more "reliable" candidate types have
++ higher numbers. So, we sort by type and then priority within
++ type
++ */
++ cand=TAILQ_FIRST(&comp->candidates);
++ while(cand){
++ if (!best_cand) {
++ best_cand = cand;
++ }
++ else {
++ if (best_cand->type < cand->type) {
++ best_cand = cand;
++ } else if (best_cand->type == cand->type) {
++ if (best_cand->priority < cand->priority)
++ best_cand = cand;
++ }
++ }
++
++ cand=TAILQ_NEXT(cand,entry_comp);
++ }
++
++ /* No candidates */
++ if (!best_cand)
++ ABORT(R_NOT_FOUND);
++
++ *candp = best_cand;
++
++ _status=0;
++ abort:
++ return(_status);
++ }
++
++
+ int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream)
+ {
+ int r,_status;
+ nr_ice_component *pcomp,*lcomp;
+
+ pcomp=STAILQ_FIRST(&pstream->components);
+ lcomp=STAILQ_FIRST(&lstream->components);
+ while(pcomp){
+ if(r=nr_ice_component_pair_candidates(pctx,lcomp,pcomp))
+ ABORT(r);
+-
++
+ lcomp=STAILQ_NEXT(lcomp,entry);
+ pcomp=STAILQ_NEXT(pcomp,entry);
+ };
+
++ if (pstream->ice_state == NR_ICE_MEDIA_STREAM_UNPAIRED) {
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): unfreezing stream %s",pstream->pctx->label,pstream->label);
++ pstream->ice_state = NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
++ }
++
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+ /* S 5.8 -- run the highest priority WAITING pair or if not available
+ FROZEN pair */
+-static void nr_ice_media_stream_check_timer_cb(int s, int h, void *cb_arg)
++static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
+ {
+ int r,_status;
+ nr_ice_media_stream *stream=cb_arg;
+ nr_ice_cand_pair *pair;
+ int timer_val;
+
+ assert(stream->pctx->active_streams!=0);
+
+ timer_val=stream->pctx->ctx->Ta*stream->pctx->active_streams;
+
++ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): bogus state for stream %s",stream->pctx->label,stream->label);
++ }
+ assert(stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
+
+ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): check timer expired for media stream %s",stream->pctx->label,stream->label);
+ stream->timer=0;
+
+-
+ /* Find the highest priority WAITING check and move it to RUNNING */
+ pair=TAILQ_FIRST(&stream->check_list);
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_WAITING)
+ break;
+ pair=TAILQ_NEXT(pair,entry);
+ }
+
+ /* Hmmm... No WAITING. Let's look for FROZEN */
+ if(!pair){
+ pair=TAILQ_FIRST(&stream->check_list);
+-
++
+ while(pair){
+ if(pair->state==NR_ICE_PAIR_STATE_FROZEN){
+ if(r=nr_ice_candidate_pair_unfreeze(stream->pctx,pair))
+ ABORT(r);
+ break;
+ }
+ pair=TAILQ_NEXT(pair,entry);
+ }
+ }
+
+ if(pair){
+ nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
+ NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
+ }
++ /* TODO(ekr@rtfm.com): Report on the special case where there are no checks to
++ run at all */
+ _status=0;
+ abort:
+ return;
+ }
+
+
+ /* Start checks for this media stream (aka check list) */
+ int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
+ {
+ assert(stream->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FROZEN);
+@@ -476,21 +539,23 @@
+ /* All done... */
+ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all components have nominated candidate pairs",stream->pctx->label,stream->label);
+ nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
+
+ /* Cancel our timer */
+ if(stream->timer){
+ NR_async_timer_cancel(stream->timer);
+ stream->timer=0;
+ }
+
+- stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
++ if (stream->pctx->handler) {
++ stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream);
++ }
+
+ /* Now tell the peer_ctx that we're done */
+ if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
+ ABORT(r);
+
+ done:
+ _status=0;
+ abort:
+ return(_status);
+ }
+@@ -515,21 +580,23 @@
+
+ p2=TAILQ_NEXT(p2,entry);
+ }
+
+ /* Cancel our timer */
+ if(stream->timer){
+ NR_async_timer_cancel(stream->timer);
+ stream->timer=0;
+ }
+
+- stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
++ if (stream->pctx->handler) {
++ stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream);
++ }
+
+ /* Now tell the peer_ctx that we're done */
+ if(r=nr_ice_peer_ctx_stream_done(stream->pctx,stream))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h src/ice/ice_media_stream.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_media_stream.h 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_media_stream.h 2012-10-06 08:30:22.000000000 -0700
+@@ -45,40 +45,43 @@
+ struct nr_ice_peer_ctx_ *pctx;
+
+ struct nr_ice_media_stream_ *local_stream; /* used when this is a peer */
+ int component_ct;
+ nr_ice_component_head components;
+
+ char *ufrag; /* ICE username */
+ char *pwd; /* ICE password */
+
+ int ice_state;
+-#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 1
+-#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 2
+-#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 3
+-#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 4
++
++#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
++#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
++#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 3
++#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 4
++#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
+
+ nr_ice_cand_pair_head check_list;
+ void *timer; /* Check list periodic timer */
+
+ // nr_ice_cand_pair_head valid_list;
+-
++
+ STAILQ_ENTRY(nr_ice_media_stream_) entry;
+ };
+
+ typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head;
+
+ int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp);
+ int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp);
+ int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr);
+ int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream);
+ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp,int *attrctp);
++int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int component, nr_ice_candidate **candp);
+ int nr_ice_media_stream_pair_candidates(nr_ice_peer_ctx *pctx,nr_ice_media_stream *lstream,nr_ice_media_stream *pstream);
+ int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+ int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+ int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation);
+ int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out);
+ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component);
+ int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component);
+ int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
+ int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp);
+ int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx,nr_ice_media_stream *str, int component, UCHAR *data, int len);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c src/ice/ice_parser.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_parser.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_parser.c 2012-10-06 08:30:22.000000000 -0700
+@@ -35,20 +35,21 @@
+ static char *RCSSTRING __UNUSED__="$Id: ice_parser.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+ #include <csi_platform.h>
+ #include <sys/types.h>
+ #ifdef WIN32
+ #include <winsock2.h>
+ #else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
++#include <strings.h>
+ #endif
+ #include <string.h>
+ #include <assert.h>
+ #include <ctype.h>
+ #include "nr_api.h"
+ #include "ice_ctx.h"
+ #include "ice_candidate.h"
+ #include "ice_reg.h"
+
+ static void
+@@ -125,21 +126,21 @@
+ char *rel_addr=0;
+
+ if(!(cand=RCALLOC(sizeof(nr_ice_candidate))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(cand->label=r_strdup(orig)))
+ ABORT(R_NO_MEMORY);
+
+ cand->ctx=ctx;
+ cand->isock=0;
+- cand->state=NR_ICE_CAND_PEER_CANDIDATE;
++ cand->state=NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED;
+ cand->stream=stream;
+ skip_whitespace(&str);
+
+ /* Candidate attr */
+ if (strncasecmp(str, "candidate:", 10))
+ ABORT(R_BAD_DATA);
+
+ fast_forward(&str, 10);
+ if (*str == '\0')
+ ABORT(R_BAD_DATA);
+@@ -311,26 +312,31 @@
+ /* it's expected to be at EOD at this point */
+
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ skip_whitespace(&str);
+
+- assert(strlen(str) == 0);
+-
++ /* This used to be an assert, but we don't want to exit on invalid
++ remote data */
++ if (strlen(str) != 0) {
++ ABORT(R_BAD_DATA);
++ }
++
+ *candp=cand;
+
+ _status=0;
+ abort:
++ /* TODO(ekr@rtfm.com): Fix memory leak if we have a parse error */
+ if (_status)
+ r_log(LOG_ICE,LOG_WARNING,"ICE(%s): Error parsing attribute: %s",ctx->label,orig);
+
+ RFREE(connection_address);
+ RFREE(rel_addr);
+ return(_status);
+ }
+
+
+ int
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c src/ice/ice_peer_ctx.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_peer_ctx.c 2012-10-06 08:30:22.000000000 -0700
+@@ -35,33 +35,35 @@
+ static char *RCSSTRING __UNUSED__="$Id: ice_peer_ctx.c,v 1.2 2008/04/28 17:59:01 ekr Exp $";
+
+ #include <string.h>
+ #include <assert.h>
+ #include <nr_api.h>
+ #include "ice_ctx.h"
+ #include "ice_peer_ctx.h"
+ #include "nr_crypto.h"
+ #include "async_timer.h"
+
+-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg);
++static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
++static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct);
++static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate);
+
+ int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp)
+ {
+ int r,_status;
+ nr_ice_peer_ctx *pctx=0;
+
+ if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ if(!(pctx->label=r_strdup(label)))
+ ABORT(R_NO_MEMORY);
+-
++
+ pctx->ctx=ctx;
+ pctx->handler=handler;
+
+ /* Decide controlling vs. controlled */
+ if(ctx->flags & NR_ICE_CTX_FLAGS_LITE){
+ if(pctx->peer_lite){
+ r_log(LOG_ICE,LOG_ERR,"Both sides are ICE-Lite");
+ ABORT(R_BAD_DATA);
+ }
+
+@@ -88,85 +90,177 @@
+ nr_ice_peer_ctx_destroy_cb(0,0,pctx);
+ }
+ return(_status);
+ }
+
+
+
+ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct)
+ {
+ nr_ice_media_stream *pstream=0;
+- nr_ice_candidate *cand=0;
+ nr_ice_component *comp,*comp2;
+ int r,_status;
+- int i,j;
+
+- /* Note: use component_ct from our own stream since components other
+- than this offered by the other side are unusable */
++ /*
++ Note: use component_ct from our own stream since components other
++ than this offered by the other side are unusable */
+ if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream))
+ ABORT(r);
+-
+- /* Match up the local and remote components */
++
++ /* Match up the local and remote components */
+ comp=STAILQ_FIRST(&stream->components);
+ comp2=STAILQ_FIRST(&pstream->components);
+ while(comp){
+ comp2->local_component=comp;
+
+ comp=STAILQ_NEXT(comp,entry);
+ comp2=STAILQ_NEXT(comp2,entry);
+ }
+-
+
+- pstream->ice_state=NR_ICE_MEDIA_STREAM_CHECKS_FROZEN;
+ pstream->local_stream=stream;
+ pstream->pctx=pctx;
+
++ if (r=nr_ice_peer_ctx_parse_stream_attributes_int(pctx,stream,pstream,attrs,attr_ct))
++ ABORT(r);
++
++
++ STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
++
++ _status=0;
++ abort:
++ return(_status);
++ }
++
++static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, nr_ice_media_stream *pstream, char **attrs, int attr_ct)
++ {
++ int r;
++ int i;
++
+ for(i=0;i<attr_ct;i++){
+ if(!strncmp(attrs[i],"ice-",4)){
+- if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i]))
++ if(r=nr_ice_peer_ctx_parse_media_stream_attribute(pctx,pstream,attrs[i])) {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus ICE attribute",pctx->ctx->label,pctx->label);
+ continue;
+- continue;
++ }
+ }
+-
+- if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,attrs[i],pstream,&cand))
+- continue;
+- if(cand->component_id-1>=pstream->component_ct){
+- r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
+- continue;
++ else if (!strncmp(attrs[i],"candidate",9)){
++ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,attrs[i])) {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus candidate",pctx->ctx->label,pctx->label);
++ continue;
++ }
++ }
++ else {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified bogus attribute",pctx->ctx->label,pctx->label);
+ }
++ }
+
+- /* Not the fastest way to find a component, but it's what we got */
+- j=1;
+- for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
+- if(j==cand->component_id)
+- break;
++ /* Doesn't fail because we just skip errors */
++ return(0);
++ }
+
+- j++;
+- }
+-
+- if(!comp){
+- r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
+- ABORT(R_BAD_DATA);
+- }
+-
+- cand->component=comp;
++static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, char *candidate)
++ {
++ nr_ice_candidate *cand=0;
++ nr_ice_component *comp;
++ int j;
++ int r, _status;
+
+- TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
++ if(r=nr_ice_peer_candidate_from_attribute(pctx->ctx,candidate,pstream,&cand))
++ ABORT(r);
++ if(cand->component_id-1>=pstream->component_ct){
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) specified too many components",pctx->ctx->label,pctx->label);
++ ABORT(R_BAD_DATA);
+ }
+
+- STAILQ_INSERT_TAIL(&pctx->peer_streams,pstream,entry);
++ /* Not the fastest way to find a component, but it's what we got */
++ j=1;
++ for(comp=STAILQ_FIRST(&pstream->components);comp;comp=STAILQ_NEXT(comp,entry)){
++ if(j==cand->component_id)
++ break;
++
++ j++;
++ }
++
++ if(!comp){
++ r_log(LOG_ICE,LOG_ERR,"Peer answered with more components than we offered");
++ ABORT(R_BAD_DATA);
++ }
++
++ cand->component=comp;
++
++ TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
+
+ _status=0;
+- abort:
++ abort:
++ if (_status) {
++ nr_ice_candidate_destroy(&cand);
++ }
+ return(_status);
+ }
+
++
++
++int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
++ {
++ /* First need to find the stream. Because we don't have forward pointers,
++ iterate through all the peer streams to find one that matches us */
++ nr_ice_media_stream *pstream;
++ int r,_status;
++ int needs_pairing = 0;
++
++ pstream=STAILQ_FIRST(&pctx->peer_streams);
++ while(pstream) {
++ if (pstream->local_stream == stream)
++ break;
++
++ pstream = STAILQ_NEXT(pstream, entry);
++ }
++ if (!pstream) {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
++ ABORT(R_NOT_FOUND);
++ }
++
++ switch(pstream->ice_state) {
++ case NR_ICE_MEDIA_STREAM_UNPAIRED:
++ break;
++ case NR_ICE_MEDIA_STREAM_CHECKS_FROZEN:
++ case NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE:
++ needs_pairing = 1;
++ break;
++ default:
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) tried to trickle ICE in inappropriate state %d",pctx->ctx->label,pctx->label,stream->label,pstream->ice_state);
++ ABORT(R_ALREADY);
++ break;
++ }
++
++ if(r=nr_ice_ctx_parse_candidate(pctx,pstream,candidate)){
++ ABORT(r);
++ }
++
++ /* If ICE is running (i.e., we are in FROZEN or ACTIVE states)
++ then we need to pair this new candidate. For now we
++ just re-pair the stream which is inefficient but still
++ fine because we suppress duplicate pairing */
++ if (needs_pairing) {
++ if(r=nr_ice_media_stream_pair_candidates(pctx, stream, pstream)) {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
++ ABORT(r);
++ }
++ }
++
++ _status =0;
++ abort:
++ return(_status);
++
++ }
++
++
+ int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
+ {
+ nr_ice_media_stream *stream;
+ int r,_status;
+
+ if(STAILQ_EMPTY(&pctx->peer_streams)) {
+ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) received no media stream attribributes",pctx->ctx->label,pctx->label);
+ ABORT(R_FAILED);
+ }
+
+@@ -177,21 +271,21 @@
+ ABORT(r);
+
+ stream=STAILQ_NEXT(stream,entry);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+-static void nr_ice_peer_ctx_destroy_cb(int s, int how, void *cb_arg)
++static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_peer_ctx *pctx=cb_arg;
+ nr_ice_media_stream *str1,*str2;
+
+ RFREE(pctx->label);
+ RFREE(pctx->peer_ufrag);
+ RFREE(pctx->peer_pwd);
+
+ STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){
+ STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry);
+@@ -199,44 +293,79 @@
+ }
+
+ RFREE(pctx);
+ }
+
+ int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp)
+ {
+
+ if(!pctxp || !*pctxp)
+ return(0);
+-
++
++ /* Stop calling the handler */
++ (*pctxp)->handler = 0;
++
+ NR_ASYNC_SCHEDULE(nr_ice_peer_ctx_destroy_cb,*pctxp);
+
+ *pctxp=0;
+
+ return(0);
+ }
+
++
+ /* Start the checks for the first media stream (S 5.7)
+ The rest remain FROZEN */
+ int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx)
+ {
++ return nr_ice_peer_ctx_start_checks2(pctx, 0);
++ }
++
++/* Start checks for some media stream.
++
++ If allow_non_first == 0, then we only look at the first stream,
++ which is 5245-complaint.
++
++ If allow_non_first == 1 then we find the first non-empty stream
++ This is not compliant with RFC 5245 but is necessary to make trickle ICE
++ work plausibly
++*/
++int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first)
++ {
+ int r,_status;
+ nr_ice_media_stream *stream;
+
+ stream=STAILQ_FIRST(&pctx->peer_streams);
+ if(!stream)
+ ABORT(R_FAILED);
+
++ while (stream) {
++ if(!TAILQ_EMPTY(&stream->check_list))
++ break;
++
++ if(!allow_non_first){
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) first stream has empty check list",pctx->ctx->label,pctx->label);
++ ABORT(R_FAILED);
++ }
++
++ stream=STAILQ_NEXT(stream, entry);
++ }
++
++ if (!stream) {
++ r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) no streams with non-empty check lists",pctx->ctx->label,pctx->label);
++ ABORT(R_NOT_FOUND);
++ }
++
+ if (stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_FROZEN) {
+- if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
+- ABORT(r);
+- if(r=nr_ice_media_stream_start_checks(pctx,stream))
+- ABORT(r);
++ if(r=nr_ice_media_stream_unfreeze_pairs(pctx,stream))
++ ABORT(r);
++ if(r=nr_ice_media_stream_start_checks(pctx,stream))
++ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+ #ifndef NDEBUG
+ int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
+ {
+@@ -253,26 +382,28 @@
+ stream=STAILQ_NEXT(stream,entry);
+ }
+ fprintf(out,"==========================================\n");
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+ #endif
+
+-static void nr_ice_peer_ctx_fire_done(int s, int how, void *cb_arg)
++static void nr_ice_peer_ctx_fire_done(NR_SOCKET s, int how, void *cb_arg)
+ {
+ nr_ice_peer_ctx *pctx=cb_arg;
+
+ /* Fire the handler callback to say we're done */
+- pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
++ if (pctx->handler) {
++ pctx->handler->vtbl->ice_completed(pctx->handler->obj, pctx);
++ }
+ }
+
+
+ /* OK, a stream just went ready. Examine all the streams to see if we're
+ maybe miraculously done */
+ int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
+ {
+ int _status;
+ nr_ice_media_stream *str;
+ int failed=0;
+@@ -365,21 +496,24 @@
+ NR_TRANSPORT_ADDR_CMP_MODE_ALL))
+ break;
+
+ cand=TAILQ_NEXT(cand,entry_comp);
+ }
+
+ if(!cand)
+ ABORT(R_REJECTED);
+
+ /* OK, there's a match. Call the handler */
+- r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
+
+- pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
+- pctx,comp->stream,comp->component_id,data,len);
++ if (pctx->handler) {
++ r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s): Delivering data", pctx->label);
++
++ pctx->handler->vtbl->msg_recvd(pctx->handler->obj,
++ pctx,comp->stream,comp->component_id,data,len);
++ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h src/ice/ice_peer_ctx.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_peer_ctx.h 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_peer_ctx.h 2012-10-06 08:30:22.000000000 -0700
+@@ -33,23 +33,21 @@
+
+
+ #ifndef _ice_peer_ctx_h
+ #define _ice_peer_ctx_h
+ #ifdef __cplusplus
+ using namespace std;
+ extern "C" {
+ #endif /* __cplusplus */
+
+ struct nr_ice_peer_ctx_ {
+- int state;
+ char *label;
+-
+ nr_ice_ctx *ctx;
+ nr_ice_handler *handler;
+
+ UCHAR controlling; /* 1 for controlling, 0 for controlled */
+ UINT8 tiebreaker;
+
+ char *peer_ufrag;
+ char *peer_pwd;
+ int peer_lite;
+ int peer_ice_mismatch;
+@@ -59,23 +57,26 @@
+ int waiting_pairs;
+
+ STAILQ_ENTRY(nr_ice_peer_ctx_) entry;
+ };
+
+ typedef STAILQ_HEAD(nr_ice_peer_ctx_head_, nr_ice_peer_ctx_) nr_ice_peer_ctx_head;
+
+ int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label, nr_ice_peer_ctx **pctxp);
+ int nr_ice_peer_ctx_destroy(nr_ice_peer_ctx **pctxp);
+ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char **attrs, int attr_ct);
++int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *cand);
++
+ int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx);
+ int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int attr_ct);
+ int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
++int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
+ int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out);
+ int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx);
+ int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
+ int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
+ int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #endif
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c src/ice/ice_socket.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/ice/ice_socket.c 2012-09-16 16:26:08.000000000 -0700
++++ src/ice/ice_socket.c 2012-10-06 08:30:22.000000000 -0700
+@@ -216,28 +216,34 @@
+ RFREE(s1);
+ }
+
+ RFREE(isock);
+
+ return(0);
+ }
+
+ int nr_ice_socket_close(nr_ice_socket *isock)
+ {
++#ifdef NR_SOCKET_IS_VOID_PTR
++ NR_SOCKET fd=NULL;
++ NR_SOCKET no_socket = NULL;
++#else
+ NR_SOCKET fd=-1;
++ NR_SOCKET no_socket = -1;
++#endif
+
+ if (!isock||!isock->sock)
+ return(0);
+
+ nr_socket_getfd(isock->sock,&fd);
+ assert(isock->sock!=0);
+- if(fd!=-1){
++ if(fd != no_socket){
+ NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_READ);
+ NR_ASYNC_CANCEL(fd,NR_ASYNC_WAIT_WRITE);
+ nr_socket_destroy(&isock->sock);
+ }
+
+ return(0);
+ }
+
+ int nr_ice_socket_register_stun_client(nr_ice_socket *sock, nr_stun_client_ctx *srv,void **handle)
+ {
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h src/net/nr_socket.h
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/nr_socket.h 2012-09-16 16:26:09.000000000 -0700
++++ src/net/nr_socket.h 2012-10-06 08:30:22.000000000 -0700
+@@ -38,21 +38,23 @@
+ #include <sys/types.h>
+ #ifdef WIN32
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #else
+ #include <sys/socket.h>
+ #endif
+
+ #include "transport_addr.h"
+
+-#ifdef WIN32
++#ifdef __cplusplus
++#define restrict
++#elif defined(WIN32)
+ #define restrict __restrict
+ #endif
+
+ typedef struct nr_socket_vtbl_ {
+ int (*destroy)(void **obj);
+ int (*ssendto)(void *obj,const void *msg, size_t len, int flags,
+ nr_transport_addr *addr);
+ int (*srecvfrom)(void *obj,void * restrict buf, size_t maxlen, size_t *len, int flags,
+ nr_transport_addr *addr);
+ int (*getfd)(void *obj, NR_SOCKET *fd);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c src/net/transport_addr_reg.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/net/transport_addr_reg.c 2012-09-16 16:26:09.000000000 -0700
++++ src/net/transport_addr_reg.c 2012-10-06 08:30:22.000000000 -0700
+@@ -29,25 +29,27 @@
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+ static char *RCSSTRING __UNUSED__="$Id: transport_addr_reg.c,v 1.2 2008/04/28 17:59:03 ekr Exp $";
+
+ #include <csi_platform.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <memory.h>
+ #include <sys/types.h>
+ #ifdef WIN32
+ #include <winsock2.h>
+ #else
++#include <strings.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #endif
+ #include <assert.h>
+ #include "nr_api.h"
+ #include "transport_addr.h"
+ #include "transport_addr_reg.h"
+
+@@ -83,20 +85,22 @@
+
+ if ((r=NR_reg_get2_uint2(prefix, "port", &port))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ port = 0;
+ }
+
+ if ((r=NR_reg_alloc2_string(prefix, "protocol", &protocol))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
++ p = IPPROTO_UDP;
++
+ protocol = 0;
+ }
+ else {
+ if (!strcasecmp("tcp", protocol))
+ p = IPPROTO_TCP;
+ else if (!strcasecmp("udp", protocol))
+ p = IPPROTO_UDP;
+ else
+ ABORT(R_BAD_DATA);
+ }
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c src/stun/addrs.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/addrs.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/addrs.c 2012-10-06 09:42:43.000000000 -0700
+@@ -46,20 +46,22 @@
+ #include <sys/sysctl.h>
+ #include <sys/param.h>
+ #include <sys/socket.h>
+ #include <sys/syslog.h>
+ #include <net/if.h>
+ #ifndef LINUX
+ #include <net/if_var.h>
+ #include <net/if_dl.h>
+ #include <net/if_types.h>
+ #include <sys/sockio.h>
++#else
++#include <linux/if.h>
+ #endif
+ #include <net/route.h>
+
+ /* IP */
+ #include <netinet/in.h>
+ #ifdef LINUX
+ #include "sys/ioctl.h"
+ #else
+ #include <netinet/in_var.h>
+ #endif
+@@ -105,20 +107,23 @@
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #include <err.h>
+
+ static void stun_rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *);
+ static int stun_grab_addrs(char *name, int addrcount,
+ struct ifa_msghdr *ifam,
+ nr_transport_addr addrs[], int maxaddrs, int *count);
++static int
++nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr);
++
+
+ /*
+ * Expand the compacted form of addresses as returned via the
+ * configuration read via sysctl().
+ */
+ #define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+ #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+ static void
+@@ -135,21 +140,21 @@
+ continue;
+ rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+ ADVANCE(cp, sa);
+ }
+ }
+
+ static int
+ stun_grab_addrs(char *name, int addrcount, struct ifa_msghdr *ifam, nr_transport_addr addrs[], int maxaddrs, int *count)
+ {
+ int r,_status;
+- NR_SOCKET s = -1;
++ int s = -1;
+ struct ifreq ifr;
+ struct rt_addrinfo info;
+ struct sockaddr_in *sin;
+
+ ifr.ifr_addr.sa_family = AF_INET;
+ strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+
+ if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "unable to obtain addresses from socket");
+ ABORT(R_FAILED);
+@@ -180,21 +185,20 @@
+ addrcount--;
+
+ if (*count >= maxaddrs) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Address list truncated at %d out of entries", maxaddrs, maxaddrs+addrcount);
+ break;
+ }
+
+ ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
+ }
+
+-
+ _status = 0;
+ abort:
+ if (s != -1) close(s);
+ return _status;
+ }
+
+ static int
+ stun_get_mib_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
+ {
+ int _status;
+@@ -551,44 +555,48 @@
+ #else
+
+ static int
+ stun_get_siocgifconf_addrs(nr_transport_addr addrs[], int maxaddrs, int *count)
+ {
+ struct ifconf ifc;
+ int _status;
+ int s = socket( AF_INET, SOCK_DGRAM, 0 );
+ int len = 100 * sizeof(struct ifreq);
+ int r;
++ int e;
++ char *ptr;
++ int tl;
++ int n;
++ struct ifreq ifr2;
+
+ char buf[ len ];
+
+ ifc.ifc_len = len;
+ ifc.ifc_buf = buf;
+
+- int e = ioctl(s,SIOCGIFCONF,&ifc);
+- char *ptr = buf;
+- int tl = ifc.ifc_len;
+- int n=0;
++ e = ioctl(s,SIOCGIFCONF,&ifc);
++ ptr = buf;
++ tl = ifc.ifc_len;
++ n=0;
+
+ while ( (tl > 0) && ( n < maxaddrs) )
+ {
+ struct ifreq* ifr = (struct ifreq *)ptr;
+
+ #ifdef LINUX
+- int si = sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr);
++ int si = sizeof(struct ifreq);
+ #else
+ int si = sizeof(ifr->ifr_name) + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr));
+ #endif
+ tl -= si;
+ ptr += si;
+
+- struct ifreq ifr2;
+ ifr2 = *ifr;
+
+ e = ioctl(s,SIOCGIFADDR,&ifr2);
+ if ( e == -1 )
+ {
+ continue;
+ }
+
+ //r_log(NR_LOG_STUN, LOG_ERR, "ioctl addr e = %d",e);
+
+@@ -603,21 +611,21 @@
+
+ close(s);
+
+ *count = n;
+
+ _status = 0;
+ return _status;
+ }
+ #endif
+
+-int
++static int
+ nr_stun_is_duplicate_addr(nr_transport_addr addrs[], int count, nr_transport_addr *addr)
+ {
+ int i;
+ int different;
+
+ for (i = 0; i < count; ++i) {
+ different = nr_transport_addr_cmp(&addrs[i], addr, NR_TRANSPORT_ADDR_CMP_MODE_ALL);
+ if (!different)
+ return 1; /* duplicate */
+ }
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c src/stun/nr_socket_turn.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/nr_socket_turn.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/nr_socket_turn.c 2012-10-06 08:30:22.000000000 -0700
+@@ -246,17 +246,19 @@
+ default:
+ assert(0);
+ break;
+ }
+
+ return R_FAILED;
+ }
+
+ static int nr_socket_turn_close(void *obj)
+ {
++#ifndef NDEBUG
+ nr_socket_turn *sturn=obj;
+ assert(sturn->magic_cookie == nr_socket_turn_magic_cookie);
++#endif
+
+ return 0;
+ }
+
+ #endif /* USE_TURN */
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c src/stun/stun_client_ctx.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/stun_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
+@@ -38,21 +38,22 @@
+ #include <string.h>
+
+ #include <nr_api.h>
+ #include "stun.h"
+ #include "async_timer.h"
+ #include "registry.h"
+ #include "stun_reg.h"
+ #include "r_time.h"
+
+ static int nr_stun_client_send_request(nr_stun_client_ctx *ctx);
+-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg);
++static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg);
++static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password);
+
+ int nr_stun_client_ctx_create(char *label, nr_socket *sock, nr_transport_addr *peer, UINT4 RTO, nr_stun_client_ctx **ctxp)
+ {
+ nr_stun_client_ctx *ctx=0;
+ int r,_status;
+
+ if ((r=nr_stun_startup()))
+ ABORT(r);
+
+ if(!(ctx=RCALLOC(sizeof(nr_stun_client_ctx))))
+@@ -185,21 +186,21 @@
+ ctx->finished_cb = 0;
+ ctx->cb_arg = 0;
+ ctx->request_ct = 0;
+ ctx->timeout_ms = 0;
+
+ ctx->state = NR_STUN_CLIENT_STATE_INITTED;
+
+ return 0;
+ }
+
+-static void nr_stun_client_timer_expired_cb(int a, int b, void *cb_arg)
++static void nr_stun_client_timer_expired_cb(NR_SOCKET s, int b, void *cb_arg)
+ {
+ int _status;
+ nr_stun_client_ctx *ctx=cb_arg;
+ struct timeval now;
+ INT8 ms_waited;
+
+ /* Prevent this timer from being cancelled later */
+ ctx->timer_handle=0;
+
+ /* Shouldn't happen */
+@@ -387,21 +388,21 @@
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ ctx->state=NR_STUN_CLIENT_STATE_FAILED;
+ }
+ return(_status);
+ }
+
+-int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
++static int nr_stun_client_get_password(void *arg, nr_stun_message *msg, Data **password)
+ {
+ *password = (Data*)arg;
+ if (!arg)
+ return(R_NOT_FOUND);
+ return(0);
+ }
+
+ int nr_stun_client_process_response(nr_stun_client_ctx *ctx, UCHAR *msg, int len, nr_transport_addr *peer_addr)
+ {
+ int r,_status;
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c src/stun/stun_codec.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_codec.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/stun_codec.c 2012-10-06 08:30:22.000000000 -0700
+@@ -73,20 +73,22 @@
+ static int nr_stun_decode_htonll(UCHAR *buf, int buflen, int *offset, UINT8 *data);
+ static int nr_stun_decode(int length, UCHAR *buf, int buflen, int *offset, UCHAR *data);
+
+ static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, int len, void *data, int max_bytes, int max_chars);
+
+ static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+ static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+ static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+ static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
+ static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, int attrlen, void *data);
++static int
++nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data);
+
+
+ int
+ nr_stun_encode_htons(UINT2 data, int buflen, UCHAR *buf, int *offset)
+ {
+ UINT2 d = htons(data);
+
+ if (*offset + sizeof(d) >= buflen) {
+ r_log(NR_LOG_STUN, LOG_WARNING, "Attempted buffer overrun: %d + %d >= %d", *offset, sizeof(d), buflen);
+ return R_BAD_DATA;
+@@ -632,21 +634,21 @@
+ }
+
+ fingerprint->checksum = checksum ^ 0x5354554e;
+
+ r_log(NR_LOG_STUN, LOG_DEBUG, "Computed FINGERPRINT %08x", fingerprint->checksum);
+
+ fingerprint->valid = 1;
+ return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen);
+ }
+
+-int
++static int
+ nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, int attrlen, UCHAR *buf, int offset, int buflen, void *data)
+ {
+ int r,_status;
+ nr_stun_attr_fingerprint *fingerprint = data;
+ nr_stun_message_header *header = (nr_stun_message_header*)buf;
+ int length;
+ UINT4 checksum;
+
+ if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum)))
+ ABORT(r);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c src/stun/stun_proc.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_proc.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/stun_proc.c 2012-10-06 08:30:22.000000000 -0700
+@@ -43,20 +43,22 @@
+ #include <time.h>
+ #else /* UNIX */
+ #include <string.h>
+ #endif /* end UNIX */
+ #include <assert.h>
+
+ #include "stun.h"
+ #include "stun_reg.h"
+ #include "registry.h"
+
++static int
++nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
+
+ /* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
+ int
+ nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
+ {
+ int _status;
+ nr_stun_message_attribute *attr;
+
+ #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
+ /* if this message was generated by an RFC 3489 impementation,
+@@ -371,21 +373,21 @@
+ /* nothing to check in this case */
+ break;
+ #endif /* USE_STUND_0_96 */
+ }
+
+ _status=0;
+ abort:
+ return _status;
+ }
+
+-int
++static int
+ nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
+ {
+ int r,_status;
+ char *realm = 0;
+ char *nonce;
+ UINT2 size;
+
+ if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
+ ABORT(r);
+
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c src/stun/stun_server_ctx.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_server_ctx.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/stun_server_ctx.c 2012-10-06 08:30:22.000000000 -0700
+@@ -114,21 +114,21 @@
+ STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
+
+ _status=0;
+ abort:
+ if(_status){
+ nr_stun_server_destroy_client(clnt);
+ }
+ return(_status);
+ }
+
+-int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
++static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
+ {
+ int _status;
+ nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
+ nr_stun_server_client *clnt = 0;
+ nr_stun_message_attribute *username_attribute;
+
+ if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
+ if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
+ r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Missing Username",ctx->label);
+ ABORT(R_NOT_FOUND);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c src/stun/stun_util.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/stun_util.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/stun_util.c 2012-10-06 08:30:22.000000000 -0700
+@@ -94,21 +94,20 @@
+ _status = 0;
+ abort:
+ return _status;
+ }
+
+ int
+ nr_stun_find_local_addresses(nr_transport_addr addrs[], int maxaddrs, int *count)
+ {
+ int r,_status;
+ NR_registry *children = 0;
+- int i;
+
+ if ((r=NR_reg_get_child_count(NR_STUN_REG_PREF_ADDRESS_PRFX, (unsigned int*)count)))
+ if (r == R_NOT_FOUND)
+ *count = 0;
+ else
+ ABORT(r);
+
+ if (*count == 0) {
+ if ((r=nr_stun_get_addrs(addrs, maxaddrs, 1, count)))
+ ABORT(r);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c src/stun/turn_client_ctx.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/stun/turn_client_ctx.c 2012-09-16 16:26:10.000000000 -0700
++++ src/stun/turn_client_ctx.c 2012-10-06 08:30:22.000000000 -0700
+@@ -55,21 +55,24 @@
+ };
+
+ static int TURN_PHASE_MODE[NUMBER_OF_STUN_CTX] = {
+ NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST1,
+ NR_TURN_CLIENT_MODE_ALLOCATE_REQUEST2,
+ NR_TURN_CLIENT_MODE_SET_ACTIVE_DEST_REQUEST
+ };
+
+
+ static int nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state);
+-static void nr_turn_client_cb(int s, int how, void *cb_arg);
++static void nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg);
++static int
++nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg);
++
+
+ int
+ nr_turn_client_next_action(nr_turn_client_ctx *ctx, int stun_ctx_state)
+ {
+ int r,_status;
+
+ assert(ctx->phase >= -1 && ctx->phase < NUMBER_OF_STUN_CTX);
+
+ switch (ctx->state) {
+ //case NR_TURN_CLIENT_STATE_ALLOCATING:
+@@ -147,21 +150,21 @@
+ * because as a side effect this ctx may be operated on in the
+ * callback */
+ finished_cb(0,0,ctx->cb_arg);
+ }
+ }
+
+ return(_status);
+ }
+
+ void
+-nr_turn_client_cb(int s, int how, void *cb_arg)
++nr_turn_client_cb(NR_SOCKET s, int how, void *cb_arg)
+ {
+ int r,_status;
+ nr_turn_client_ctx *ctx = (nr_turn_client_ctx*)cb_arg;
+ nr_stun_client_ctx *stun_ctx = ctx->stun_ctx[ctx->phase];
+
+ assert(ctx->phase >= 0);
+
+ if ((r=nr_turn_client_next_action(ctx, stun_ctx->state)))
+ ABORT(r);
+
+@@ -234,21 +237,21 @@
+
+ RFREE(ctx->username);
+ r_data_destroy(&ctx->password);
+
+ RFREE(ctx->label);
+ RFREE(ctx);
+
+ return(0);
+ }
+
+-int
++static int
+ nr_turn_client_prepare_start(nr_turn_client_ctx *ctx, char *username, Data *password, UINT4 bandwidth_kbps, UINT4 lifetime_secs, NR_async_cb finished_cb, void *cb_arg)
+ {
+ int r,_status;
+ nr_stun_client_allocate_request1_params *allocate_request1 = 0;
+ nr_stun_client_allocate_request2_params *allocate_request2 = 0;
+ nr_stun_client_allocate_response1_results *allocate_response1 = 0;
+ // nr_stun_client_allocate_response2_results *allocate_response2;
+
+ if (ctx->state != NR_TURN_CLIENT_STATE_INITTED)
+ ABORT(R_NOT_PERMITTED);
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c src/util/ice_util.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/ice_util.c 2012-09-16 16:26:10.000000000 -0700
++++ src/util/ice_util.c 2012-10-06 08:30:22.000000000 -0700
+@@ -31,20 +31,21 @@
+ */
+
+ #include <stdarg.h>
+
+
+ static char *RCSSTRING __UNUSED__="$Id: ice_util.c,v 1.2 2008/04/28 17:59:05 ekr Exp $";
+
+ #include <stdarg.h>
+ #include <string.h>
+ #include "nr_api.h"
++#include "ice_util.h"
+
+ int nr_concat_strings(char **outp,...)
+ {
+ va_list ap;
+ char *s,*out=0;
+ int len=0;
+ int _status;
+
+ va_start(ap,outp);
+ while(s=va_arg(ap,char *)){
+diff -U10 -r /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c src/util/mbslen.c
+--- /Users/ekr/dev/mtransport-import-references/nICEr/src/util/mbslen.c 2012-09-16 16:26:10.000000000 -0700
++++ src/util/mbslen.c 2012-10-06 08:31:01.000000000 -0700
+@@ -56,21 +56,21 @@
+ {
+ #ifdef DARWIN
+ static locale_t loc = 0;
+ static int initialized = 0;
+ #endif /* DARWIN */
+ #ifdef WIN32
+ char *my_locale=0;
+ unsigned int i;
+ #endif /* WIN32 */
+ int _status;
+- int nbytes;
++ size_t nbytes;
+ int nchars;
+ mbstate_t mbs;
+
+ #ifdef DARWIN
+ if (! initialized) {
+ initialized = 1;
+ loc = newlocale(LC_CTYPE_MASK, "UTF-8", LC_GLOBAL_LOCALE);
+ }
+
+ if (loc == 0) {
+@@ -102,25 +102,28 @@
+
+ memset(&mbs, 0, sizeof(mbs));
+ nchars = 0;
+
+ #ifdef DARWIN
+ while (*s != '\0' && (nbytes = mbrlen_l(s, strlen(s), &mbs, loc)) != 0)
+ #else
+ while (*s != '\0' && (nbytes = mbrlen(s, strlen(s), &mbs)) != 0)
+ #endif /* DARWIN */
+ {
+- assert(nbytes >= 0);
+- if (nbytes == (size_t)-1) /* should never happen */
++ if (nbytes == (size_t)-1) /* should never happen */ {
++ assert(0);
+ ABORT(R_INTERNAL);
+- if (nbytes == (size_t)-2) /* encoding error */
++ }
++ if (nbytes == (size_t)-2) /* encoding error */ {
++ assert(0);
+ ABORT(R_BAD_DATA);
++ }
+
+ s += nbytes;
+ ++nchars;
+ }
+
+ *ncharsp = nchars;
+
+ _status = 0;
+ abort:
+ #ifdef WIN32
diff --git a/media/mtransport/third_party/nrappkit/COPYRIGHT b/media/mtransport/third_party/nrappkit/COPYRIGHT
new file mode 100644
index 000000000..b0bb25595
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/COPYRIGHT
@@ -0,0 +1,159 @@
+
+Copyright (C) 2006, Network Resonance, Inc.
+All Rights Reserved
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+This distribution also contains material from ssldump, tcpdump, and
+FreeBSD. The licenses are on the individual source files but follow
+here as well.
+
+SSLDUMP LICENSE
+Copyright (C) 1999-2001 RTFM, Inc.
+All Rights Reserved
+
+This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+<ekr@rtfm.com> and licensed by RTFM, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE ERIC RESCORLA AND RTFM ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+TCPDUMP LICENSE
+The manual page for this software is partially excerpted from
+the tcpdump manual page, which is subject to the following license:
+Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+ The Regents of the University of California. All rights reserved.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that: (1) source code distributions
+retain the above copyright notice and this paragraph in its entirety, (2)
+distributions including binary code include the above copyright notice and
+this paragraph in its entirety in the documentation or other materials
+provided with the distribution, and (3) all advertising materials mentioning
+features or use of this software display the following acknowledgement:
+``This product includes software developed by the University of California,
+Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+the University nor the names of its contributors may be used to endorse
+or promote products derived from this software without specific prior
+written permission.
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+
+The compilation of software known as FreeBSD is distributed under the
+following terms:
+
+Copyright (C) 1992-2004 The FreeBSD Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The 4.4BSD and 4.4BSD-Lite software is distributed under the following
+terms:
+
+All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite
+Releases is copyrighted by The Regents of the University of California.
+
+Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ The Regents of the University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
diff --git a/media/mtransport/third_party/nrappkit/IMPORT_FILES b/media/mtransport/third_party/nrappkit/IMPORT_FILES
new file mode 100644
index 000000000..0f80a52e3
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/IMPORT_FILES
@@ -0,0 +1,87 @@
+ # API
+ src/plugin/nr_plugin.h
+ src/share/nr_api.h
+ src/share/nr_common.h
+ src/share/nr_reg_keys.h
+
+ # libekr
+ src/util/libekr/assoc.h
+ src/util/libekr/debug.c
+ src/util/libekr/debug.h
+ src/util/libekr/r_assoc.c
+ src/util/libekr/r_assoc.h
+ src/util/libekr/r_common.h
+ src/util/libekr/r_crc32.c
+ src/util/libekr/r_crc32.h
+ src/util/libekr/r_data.c
+ src/util/libekr/r_data.h
+ src/util/libekr/r_defaults.h
+ src/util/libekr/r_errors.c
+ src/util/libekr/r_errors.h
+ src/util/libekr/r_includes.h
+ src/util/libekr/r_list.c
+ src/util/libekr/r_list.h
+ src/util/libekr/r_macros.h
+ src/util/libekr/r_memory.c
+ src/util/libekr/r_memory.h
+ src/util/libekr/r_replace.c
+ src/util/libekr/r_thread.h
+ src/util/libekr/r_time.c
+ src/util/libekr/r_time.h
+ src/util/libekr/r_types.h
+ src/util/libekr/debug.c
+ src/util/libekr/debug.h
+
+ # Utilities
+ src/util/byteorder.c
+ src/util/byteorder.h
+ src/util/hex.c
+ src/util/hex.h
+ src/util/p_buf.c
+ src/util/p_buf.h
+ src/util/util.c
+ src/util/util.h
+
+ # Events
+ src/event/async_timer.h
+ src/event/async_wait.h
+ src/event/async_wait_int.h
+
+ # Logging
+ src/log/r_log.c
+ src/log/r_log.h
+
+ # Registry
+ src/registry/c2ru.c
+ src/registry/c2ru.h
+ src/registry/registry.c
+ src/registry/registry.h
+ src/registry/registry_int.h
+ src/registry/registry_local.c
+ src/registry/registry_vtbl.h
+ src/registry/registrycb.c
+
+ src/port/darwin/include/csi_platform.h
+ src/port/win32/include/csi_platform.h
+ src/port/linux/include/csi_platform.h
+ src/port/linux/include/linux_funcs.h
+ src/port/linux/include/sys/ttycom.h
+ src/port/linux/port-impl.mk
+ # sys/queue.h manually copied into src/port/generic
+
+ # Stats
+ src/stats/nrstats.h
+
+ # Meta-files
+ COPYRIGHT
+ VERSION
+ README
+
+
+
+
+
+
+
+
+
diff --git a/media/mtransport/third_party/nrappkit/README b/media/mtransport/third_party/nrappkit/README
new file mode 100644
index 000000000..9cf43319b
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/README
@@ -0,0 +1,133 @@
+$Id: README,v 1.3 2007/11/21 00:09:10 adamcain Exp $
+
+nrappkit 1.0b2
+Copyright (C) 2006 Network Resonance, Inc.
+
+
+nrappkit is a toolkit for building standalone applications and
+appliances. It provides:
+
+- registry-based configuration (with change callbacks)
+- extensible command and configuration shell
+- extensible statistics system
+- configurable logging system
+- event and timer handling
+- generic plugin system
+- launcher daemon
+
+The contents of nrappkit were extracted from Network Resonance's
+product on the theory that they were generally useful for
+application developers.
+
+THIS PACKAGE DOES NOT GRANT A LICENSE OR RIGHT TO ANY OTHER NETWORK
+RESONANCE TECHNOLOGY OR SOFTWARE.
+
+
+
+BUILDING
+
+Builds are done semi-manually with port directories for each
+platform. There are pre-existing ports to FreeBSD, Linux (Ubuntu
+and Fedora Core), and Darwin (MacOSX). To build the system:
+
+ cd src/make/<platform>
+ gmake
+
+Some of the platforms come in several variants. Most notably,
+if a platform exists in "regular" and "-appliance" variant,
+this means that the regular variant just builds binaries intended
+to be run out of the make directory (for development) and the
+appliance variant is intended to be installed in a real system.
+
+By default we want to install things owned as user "pcecap".
+Either make this user or edit the Makefile to be a user you
+like (e.g., nobody).
+
+If you want to include the 'nrsh' command-line configuration
+tool in your build, you will need to make sure the line
+ BUILD_NRSH=yes
+appears (uncommented-out) in your platform Makefile. You will
+also need to to build OpenSSL and libedit and point your nrappkit
+Makefile to the correct paths. You can obtain these packages at:
+ openssl-0.9.7l
+ http://www.openssl.org/source/openssl-0.9.7l.tar.gz
+
+ libedit-20060829-2.9
+ http://freshmeat.net/redir/editline/53029/url_tgz/libedit-20060829-2.9.tar.gz
+
+
+INSTALLING
+If you're doing an appliance as opposed to a development build,
+you'll want to install it. This is easy:
+
+ su
+ gmake install
+
+Most binaries and libraries ends up in /usr/local/pcecap while
+data files are in /var/pcecap. However, you can tweak
+this in the Makefile. By default it's all owned by pcecap.
+
+To ensure that dynamic libraries are loaded correctly at runtime,
+you'd want to make sure the right directory is included in your
+LD_LIBRARY_PATH or via ldconfig.
+
+
+QUICK TOUR
+The build makes the following binaries that you may find useful:
+
+- captured -- the launcher (the name is historical)
+- registryd -- the registry daemon
+- nrregctl -- a registry control program
+- nrsh -- the command shell (when included in build)
+- nrstatsctl -- the stats control program
+
+Using the nrcapctl script is the easiest way to interact with
+the applications. It is run as "nrcapctl <command>" with the
+following commands recognized:
+
+ startup -- fires up captured, which in turn runs and
+ initializes the registry
+
+ shutdown -- kills captured and its child processes
+
+ status -- prints the running status of captured in
+ human-readable form
+
+ stat -- prints the running status of captured in
+ a form easily parsed by scripts
+
+ enable -- alters the mode.txt file so that captured
+ starts
+
+ disable -- alters the mode.txt file so that captured
+ does not start
+
+ clear-statistics -- equivalent to "nrstatsctl -z" (requires
+ that captured be running)
+
+Note: the "start" and "stop" nrcapctl commands do nothing as they
+use components not included in nrappkit. However the associated
+script logic in nrcapctl demonstrates how additional applications
+might be launched using nrcapctl and particular registry settings.
+
+
+EXTENDING
+When things come up, they're pretty dumb. You'll probably want to
+write your own applications, otherwise it's not clear why you're doing
+this. The general idea is that you write your application using the
+facilities that nrappkit provides and then write plugins to the
+nrappkit components as necessary. So, for example, say you want
+to write a network daemon. You would:
+
+ - configure the launcher to launch your daemon (using the registry,
+ naturally).
+ - make calls to the registry to get configuration data
+ - make calls to the logging system to log data
+ - implement a stats module to record statistics
+ - write a plugin to nrsh to let people configure your parameters
+
+Examples of some of this stuff can be found in examples/demo_plugin.
+Otherwise, read the source. More documentation will be on the way,
+hopefully.
+
+
diff --git a/media/mtransport/third_party/nrappkit/README_MOZILLA b/media/mtransport/third_party/nrappkit/README_MOZILLA
new file mode 100644
index 000000000..92102c83c
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/README_MOZILLA
@@ -0,0 +1,22 @@
+This import of nrappkit is a subset of the distribution at:
+
+ nrappkit.sourceforge.net
+
+
+The last revision included in this import was on Nov 25, 2008.
+This import includes a small nunber of portability fixes that
+have been submitted to the upstream repository and are included
+in upstream.diff.
+
+
+Out of the list in the README, we use:
+
+- registry-based configuration (with change callbacks)
+ [but without the registry daemon]
+- configurable logging system
+- event and timer handling
+ [though partly reimplemented]
+
+Also, we use a bunch of the generic utilities such as string handling,
+generic hash tables in C, yet another concrete type mapping, etc.
+
diff --git a/media/mtransport/third_party/nrappkit/VERSION b/media/mtransport/third_party/nrappkit/VERSION
new file mode 100644
index 000000000..3ef69b306
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/VERSION
@@ -0,0 +1 @@
+1.0b2
diff --git a/media/mtransport/third_party/nrappkit/nrappkit.gyp b/media/mtransport/third_party/nrappkit/nrappkit.gyp
new file mode 100644
index 000000000..c6ff29999
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/nrappkit.gyp
@@ -0,0 +1,234 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# nrappkit.gyp
+#
+#
+{
+ 'targets' : [
+ {
+ 'target_name' : 'nrappkit',
+ 'type' : 'static_library',
+
+ 'include_dirs' : [
+ # EXTERNAL
+ # INTERNAL
+ 'src/event',
+ 'src/log',
+ 'src/port/generic/include',
+ 'src/registry',
+ 'src/share',
+ 'src/stats',
+ 'src/util',
+ 'src/util/libekr',
+ ],
+
+ 'sources' : [
+ # Shared
+# './src/share/nr_api.h',
+ './src/share/nr_common.h',
+# './src/share/nr_dynlib.h',
+ './src/share/nr_reg_keys.h',
+# './src/share/nr_startup.c',
+# './src/share/nr_startup.h',
+# './src/share/nrappkit_static_plugins.c',
+ './src/port/generic/include'
+
+ # libekr
+ './src/util/libekr/assoc.h',
+ './src/util/libekr/debug.c',
+ './src/util/libekr/debug.h',
+ './src/util/libekr/r_assoc.c',
+ './src/util/libekr/r_assoc.h',
+# './src/util/libekr/r_assoc_test.c',
+ './src/util/libekr/r_common.h',
+ './src/util/libekr/r_crc32.c',
+ './src/util/libekr/r_crc32.h',
+ './src/util/libekr/r_data.c',
+ './src/util/libekr/r_data.h',
+ './src/util/libekr/r_defaults.h',
+ './src/util/libekr/r_errors.c',
+ './src/util/libekr/r_errors.h',
+ './src/util/libekr/r_includes.h',
+ './src/util/libekr/r_list.c',
+ './src/util/libekr/r_list.h',
+ './src/util/libekr/r_macros.h',
+ './src/util/libekr/r_memory.c',
+ './src/util/libekr/r_memory.h',
+ './src/util/libekr/r_replace.c',
+ './src/util/libekr/r_thread.h',
+ './src/util/libekr/r_time.c',
+ './src/util/libekr/r_time.h',
+ './src/util/libekr/r_types.h',
+ './src/util/libekr/debug.c',
+ './src/util/libekr/debug.h',
+
+ # Utilities
+ './src/util/byteorder.c',
+ './src/util/byteorder.h',
+ #'./src/util/escape.c',
+ #'./src/util/escape.h',
+ #'./src/util/filename.c',
+ #'./src/util/getopt.c',
+ #'./src/util/getopt.h',
+ './src/util/hex.c',
+ './src/util/hex.h',
+ #'./src/util/mem_util.c',
+ #'./src/util/mem_util.h',
+ #'./src/util/mutex.c',
+ #'./src/util/mutex.h',
+ './src/util/p_buf.c',
+ './src/util/p_buf.h',
+ #'./src/util/ssl_util.c',
+ #'./src/util/ssl_util.h',
+ './src/util/util.c',
+ './src/util/util.h',
+ #'./src/util/util_db.c',
+ #'./src/util/util_db.h',
+
+ # Events
+# './src/event/async_timer.c',
+ './src/event/async_timer.h',
+# './src/event/async_wait.c',
+ './src/event/async_wait.h',
+ './src/event/async_wait_int.h',
+
+ # Logging
+ './src/log/r_log.c',
+ './src/log/r_log.h',
+ #'./src/log/r_log_plugin.c',
+
+ # Registry
+ './src/registry/c2ru.c',
+ './src/registry/c2ru.h',
+ #'./src/registry/mod_registry/mod_registry.c',
+ #'./src/registry/nrregctl.c',
+ #'./src/registry/nrregistryctl.c',
+ './src/registry/registry.c',
+ './src/registry/registry.h',
+ './src/registry/registry_int.h',
+ './src/registry/registry_local.c',
+ #'./src/registry/registry_plugin.c',
+ './src/registry/registry_vtbl.h',
+ './src/registry/registrycb.c',
+ #'./src/registry/registryd.c',
+ #'./src/registry/regrpc.h',
+ #'./src/registry/regrpc_client.c',
+ #'./src/registry/regrpc_client.h',
+ #'./src/registry/regrpc_client_cb.c',
+ #'./src/registry/regrpc_clnt.c',
+ #'./src/registry/regrpc_server.c',
+ #'./src/registry/regrpc_svc.c',
+ #'./src/registry/regrpc_xdr.c',
+
+ # Statistics
+ #'./src/stats/nrstats.c',
+ #'./src/stats/nrstats.h',
+ #'./src/stats/nrstats_app.c',
+ #'./src/stats/nrstats_int.h',
+ #'./src/stats/nrstats_memory.c',
+ ],
+
+ 'defines' : [
+ 'SANITY_CHECKS',
+ 'R_PLATFORM_INT_TYPES=<stdint.h>',
+ 'R_DEFINED_INT2=int16_t',
+ 'R_DEFINED_UINT2=uint16_t',
+ 'R_DEFINED_INT4=int32_t',
+ 'R_DEFINED_UINT4=uint32_t',
+ 'R_DEFINED_INT8=int64_t',
+ 'R_DEFINED_UINT8=uint64_t',
+ ],
+
+ 'conditions' : [
+ ## Mac and BSDs
+ [ 'OS == "mac"', {
+ 'defines' : [
+ 'DARWIN',
+ ],
+ }],
+ [ 'os_bsd == 1', {
+ 'defines' : [
+ 'BSD',
+ ],
+ }],
+ [ 'OS == "mac" or OS == "ios" or os_bsd == 1', {
+ 'cflags_mozilla': [
+ '-Wall',
+ '-Wno-parentheses',
+ '-Wno-strict-prototypes',
+ '-Wmissing-prototypes',
+ ],
+ 'defines' : [
+ 'HAVE_LIBM=1',
+ 'HAVE_STRDUP=1',
+ 'HAVE_STRLCPY=1',
+ 'HAVE_SYS_TIME_H=1',
+ 'HAVE_VFPRINTF=1',
+ 'NEW_STDIO'
+ 'RETSIGTYPE=void',
+ 'TIME_WITH_SYS_TIME_H=1',
+ '__UNUSED__=__attribute__((unused))',
+ ],
+
+ 'include_dirs': [
+ 'src/port/darwin/include'
+ ],
+
+ 'sources': [
+ './src/port/darwin/include/csi_platform.h',
+ ],
+ }],
+
+ ## Win
+ [ 'OS == "win"', {
+ 'defines' : [
+ 'WIN',
+ '__UNUSED__=',
+ 'HAVE_STRDUP=1',
+ 'NO_REG_RPC'
+ ],
+
+ 'include_dirs': [
+ 'src/port/win32/include'
+ ],
+
+ 'sources': [
+ './src/port/win32/include/csi_platform.h',
+ ],
+ }],
+ ## Linux
+ [ '(OS == "linux") or (OS == "android")', {
+ 'cflags_mozilla': [
+ '-Wall',
+ '-Wno-parentheses',
+ '-Wno-strict-prototypes',
+ '-Wmissing-prototypes',
+ ],
+ 'defines' : [
+ 'LINUX',
+ 'HAVE_LIBM=1',
+ 'HAVE_STRDUP=1',
+ 'HAVE_STRLCPY=1',
+ 'HAVE_SYS_TIME_H=1',
+ 'HAVE_VFPRINTF=1',
+ 'NEW_STDIO'
+ 'RETSIGTYPE=void',
+ 'TIME_WITH_SYS_TIME_H=1',
+ 'NO_REG_RPC=1',
+ '__UNUSED__=__attribute__((unused))',
+ ],
+
+ 'include_dirs': [
+ 'src/port/linux/include'
+ ],
+ 'sources': [
+ './src/port/linux/include/csi_platform.h',
+ ],
+ }]
+ ]
+ }]
+}
+
+
diff --git a/media/mtransport/third_party/nrappkit/src/event/async_timer.h b/media/mtransport/third_party/nrappkit/src/event/async_timer.h
new file mode 100644
index 000000000..544a3d44f
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/event/async_timer.h
@@ -0,0 +1,54 @@
+/**
+ async_timer.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Sun Feb 22 19:35:24 2004
+ */
+
+
+#ifndef _async_timer_h
+#define _async_timer_h
+
+
+int NR_async_timer_init(void);
+int NR_async_timer_set(int delay_ms,NR_async_cb cb,void *cb_arg,char *function,int line,void **handle);
+int NR_async_timer_cancel(void *handle);
+int NR_async_timer_update_time(struct timeval *tv);
+int NR_async_timer_next_timeout(int *delay_ms);
+int NR_async_timer_sanity_check_for_cb_deleted(NR_async_cb cb,void *cb_arg);
+
+#define NR_ASYNC_TIMER_SET(d,c,a,hp) NR_async_timer_set(d,c,a,(char *)__FUNCTION__,__LINE__,hp)
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/event/async_wait.h b/media/mtransport/third_party/nrappkit/src/event/async_wait.h
new file mode 100644
index 000000000..58bcd435e
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/event/async_wait.h
@@ -0,0 +1,83 @@
+/**
+ async_wait.h
+
+
+ Copyright (C) 2001-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Thu Dec 20 20:14:49 2001
+ */
+
+
+#ifndef _async_wait_h
+#define _async_wait_h
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <csi_platform.h>
+
+typedef void (*NR_async_cb)(NR_SOCKET resource,int how,void *arg);
+
+#define NR_ASYNC_WAIT_READ 0
+#define NR_ASYNC_WAIT_WRITE 1
+
+
+int NR_async_wait_init(void);
+int NR_async_wait(NR_SOCKET sock, int how, NR_async_cb cb,void *cb_arg,
+ char *function,int line);
+int NR_async_cancel(NR_SOCKET sock,int how);
+int NR_async_schedule(NR_async_cb cb,void *arg,char *function,int line);
+int NR_async_event_wait(int *eventsp);
+int NR_async_event_wait2(int *eventsp,struct timeval *tv);
+
+
+#ifdef NR_DEBUG_ASYNC
+#define NR_ASYNC_WAIT(s,h,cb,arg) do { \
+fprintf(stderr,"NR_async_wait(%d,%s,%s) at %s(%d)\n",s,#h,#cb,__FUNCTION__,__LINE__); \
+ NR_async_wait(s,h,cb,arg,(char *)__FUNCTION__,__LINE__); \
+} while (0)
+#define NR_ASYNC_SCHEDULE(cb,arg) do { \
+fprintf(stderr,"NR_async_schedule(%s) at %s(%d)\n",#cb,__FUNCTION__,__LINE__);\
+ NR_async_schedule(cb,arg,(char *)__FUNCTION__,__LINE__); \
+} while (0)
+#define NR_ASYNC_CANCEL(s,h) do { \
+ fprintf(stderr,"NR_async_cancel(%d,%s) at %s(%d)\n",s,#h,(char *)__FUNCTION__,__LINE__); \
+NR_async_cancel(s,h); \
+} while (0)
+#else
+#define NR_ASYNC_WAIT(a,b,c,d) NR_async_wait(a,b,c,d,(char *)__FUNCTION__,__LINE__)
+#define NR_ASYNC_SCHEDULE(a,b) NR_async_schedule(a,b,(char *)__FUNCTION__,__LINE__)
+#define NR_ASYNC_CANCEL NR_async_cancel
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/event/async_wait_int.h b/media/mtransport/third_party/nrappkit/src/event/async_wait_int.h
new file mode 100644
index 000000000..d17372d18
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/event/async_wait_int.h
@@ -0,0 +1,62 @@
+/**
+ async_wait_int.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Sun Feb 22 19:16:01 2004
+ */
+
+
+#ifndef _async_wait_int_h
+#define _async_wait_int_h
+
+
+typedef struct callback_ {
+ NR_async_cb cb;
+ void *arg;
+ int how;
+ int resource;
+ void *backptr;
+
+ char *func;
+ int free_func;
+ int line;
+ TAILQ_ENTRY(callback_) entry;
+} callback;
+
+int nr_async_create_cb(NR_async_cb cb,void *arg,int how,
+ int resource,char *func,int line,callback **cbp);
+int nr_async_destroy_cb(callback **cbp);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/log/r_log.c b/media/mtransport/third_party/nrappkit/src/log/r_log.c
new file mode 100644
index 000000000..6580626e6
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/log/r_log.c
@@ -0,0 +1,694 @@
+/**
+ r_log.c
+
+
+ Copyright (C) 2001, RTFM, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 3 15:24:38 2001
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_log.c,v 1.10 2008/11/25 22:25:18 adamcain Exp $";
+
+
+#ifdef LINUX
+#define _BSD_SOURCE
+#endif
+
+#include "r_log.h"
+#include "hex.h"
+
+#include <string.h>
+#include <errno.h>
+#ifndef _MSC_VER
+#include <strings.h>
+#include <syslog.h>
+#endif
+#include <registry.h>
+#include <time.h>
+
+
+#include "nr_common.h"
+#include "nr_reg_keys.h"
+
+
+#define LOGGING_DEFAULT_LEVEL 5
+
+int NR_LOG_LOGGING = 0;
+
+static char *log_level_strings[]={
+ "EMERG",
+ "ALERT",
+ "CRIT",
+ "ERR",
+ "WARNING",
+ "NOTICE",
+ "INFO",
+ "DEBUG"
+};
+
+static char *log_level_reg_strings[]={
+ "emergency",
+ "alert",
+ "critical",
+ "error",
+ "warning",
+ "notice",
+ "info",
+ "debug"
+};
+
+#define LOGGING_REG_PREFIX "logging"
+
+#define MAX_ERROR_STRING_SIZE 512
+
+#define R_LOG_INITTED1 1
+#define R_LOG_INITTED2 2
+
+#define LOG_NUM_DESTINATIONS 3
+
+typedef struct log_type_ {
+ char *facility_name;
+ int level[LOG_NUM_DESTINATIONS];
+ NR_registry dest_facility_key[LOG_NUM_DESTINATIONS];
+} log_type;
+
+#define MAX_LOG_TYPES 16
+
+static log_type log_types[MAX_LOG_TYPES];
+static int log_type_ct;
+
+
+typedef struct log_destination_ {
+ char *dest_name;
+ int enabled;
+ int default_level;
+ r_dest_vlog *dest_vlog;
+} log_destination;
+
+
+#define LOG_LEVEL_UNDEFINED -1
+#define LOG_LEVEL_NONE -2
+#define LOG_LEVEL_USE_DEST_DEFAULT -3
+
+static int stderr_vlog(int facility,int level,const char *format,va_list ap);
+static int syslog_vlog(int facility,int level,const char *format,va_list ap);
+static int noop_vlog(int facility,int level,const char *format,va_list ap);
+
+static log_destination log_destinations[LOG_NUM_DESTINATIONS]={
+ {
+ "stderr",
+ 0,
+ LOGGING_DEFAULT_LEVEL,
+ stderr_vlog,
+ },
+ {
+ "syslog",
+#ifndef WIN32
+ 1,
+#else
+ 0,
+#endif
+ LOGGING_DEFAULT_LEVEL,
+ syslog_vlog,
+ },
+ {
+ "extra",
+ 0,
+ LOGGING_DEFAULT_LEVEL,
+ noop_vlog,
+ },
+};
+
+static int r_log_level=LOGGING_DEFAULT_LEVEL;
+static int r_log_level_environment=0;
+static int r_log_initted=0;
+static int r_log_env_verbose=0;
+
+static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name);
+static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name);
+static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name);
+static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name);
+static int r_log_get_default_level(void);
+static int r_log_get_destinations(int usereg);
+static int r_logging_dest(int dest_index, int facility, int level);
+static int _r_log_init(int usereg);
+static int r_log_get_reg_level(NR_registry name, int *level);
+
+int r_log_register(char *facility_name,int *log_facility)
+ {
+ int i,j;
+ int level;
+ int r,_status;
+ char *buf=0;
+ NR_registry dest_prefix, dest_facility_prefix;
+
+ for(i=0;i<log_type_ct;i++){
+ if(!strcmp(facility_name,log_types[i].facility_name)){
+ *log_facility=i;
+ return(0);
+ }
+ }
+
+ if(log_type_ct==MAX_LOG_TYPES){
+ ABORT(R_INTERNAL);
+ }
+
+ i=log_type_ct;
+
+ /* Initial registration completed, increment log_type_ct */
+ log_types[i].facility_name=r_strdup(facility_name);
+ *log_facility=log_type_ct;
+ log_type_ct++;
+
+ for(j=0; j<LOG_NUM_DESTINATIONS; j++){
+ log_types[i].level[j]=LOG_LEVEL_UNDEFINED;
+
+ if(NR_reg_initted()){
+
+ if(snprintf(dest_prefix,sizeof(NR_registry),
+ "logging.%s.facility",log_destinations[j].dest_name)>=sizeof(NR_registry))
+ ABORT(R_INTERNAL);
+
+ if (r=NR_reg_make_registry(dest_prefix,facility_name,dest_facility_prefix))
+ ABORT(r);
+
+ if(snprintf(log_types[i].dest_facility_key[j],sizeof(NR_registry),
+ "%s.level",dest_facility_prefix)>=sizeof(NR_registry))
+ ABORT(R_INTERNAL);
+
+ if(!r_log_get_reg_level(log_types[i].dest_facility_key[j],&level)){
+ log_types[i].level[j]=level;
+ }
+
+ /* Set a callback for the facility's level */
+ if(r=NR_reg_register_callback(log_types[i].dest_facility_key[j],
+ NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE,
+ r_log_facility_change_cb,(void *)&(log_types[i].level[j])))
+ ABORT(r);
+ if(r=NR_reg_register_callback(log_types[i].dest_facility_key[j],
+ NR_REG_CB_ACTION_DELETE,
+ r_log_facility_delete_cb,(void *)&(log_types[i].level[j])))
+ ABORT(r);
+
+ }
+ }
+
+ _status=0;
+ abort:
+ if(_status)
+ RFREE(buf);
+ return(_status);
+ }
+
+int r_log_facility(int facility,char **typename)
+ {
+ if(facility >= 0 && facility < log_type_ct){
+ *typename=log_types[facility].facility_name;
+ return(0);
+ }
+ return(R_NOT_FOUND);
+ }
+
+static int r_log_get_reg_level(NR_registry name, int *out)
+ {
+ char level[32];
+ int r,_status;
+ int i;
+
+ if(r=NR_reg_get_string(name,level,sizeof(level)))
+ ABORT(r);
+
+ if(!strcasecmp(level,"none")){
+ *out=LOG_LEVEL_NONE;
+ return(0);
+ }
+
+ for(i=0;i<=LOG_DEBUG;i++){
+ if(!strcasecmp(level,log_level_reg_strings[i])){
+ *out=(int)i;
+ return(0);
+ }
+ }
+
+ if(i>LOG_DEBUG){
+ *out=LOG_LEVEL_UNDEFINED;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+/* Handle the case where a value changes */
+static void r_log_facility_change_cb(void *cb_arg, char action, NR_registry name)
+ {
+ int *lt_level=(int *)cb_arg;
+ int level;
+ int r,_status;
+
+ if(r=r_log_get_reg_level(name,&level))
+ ABORT(r);
+
+ *lt_level=level;
+
+ _status=0;
+ abort:
+ return;
+ }
+
+/* Handle the case where a value is deleted */
+static void r_log_facility_delete_cb(void *cb_arg, char action, NR_registry name)
+ {
+ int *lt_level=(int *)cb_arg;
+
+ *lt_level=LOG_LEVEL_UNDEFINED;
+ }
+
+int r_log(int facility,int level,const char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+
+ r_vlog(facility,level,format,ap);
+ va_end(ap);
+
+ return(0);
+ }
+
+int r_dump(int facility,int level,char *name,char *data,int len)
+ {
+ char *hex = 0;
+ int unused;
+
+ if(!r_logging(facility,level))
+ return(0);
+
+ hex=RMALLOC((len*2)+1);
+ if (!hex)
+ return(R_FAILED);
+
+ if (nr_nbin2hex((UCHAR*)data, len, hex, len*2+1, &unused))
+ strcpy(hex, "?");
+
+ if(name)
+ r_log(facility,level,"%s[%d]=%s",name,len,hex);
+ else
+ r_log(facility,level,"%s",hex);
+
+ RFREE(hex);
+ return(0);
+ }
+
+// Some platforms (notably WIN32) do not have this
+#ifndef va_copy
+ #ifdef WIN32
+ #define va_copy(dest, src) ( (dest) = (src) )
+ #else // WIN32
+ #error va_copy undefined, and semantics of assignment on va_list unknown
+ #endif //WIN32
+#endif //va_copy
+
+int r_vlog(int facility,int level,const char *format,va_list ap)
+ {
+ char log_fmt_buf[MAX_ERROR_STRING_SIZE];
+ char *level_str="unknown";
+ char *facility_str="unknown";
+ char *fmt_str=(char *)format;
+ int i;
+
+ if(r_log_env_verbose){
+ if((level>=LOG_EMERG) && (level<=LOG_DEBUG))
+ level_str=log_level_strings[level];
+
+ if(facility >= 0 && facility < log_type_ct)
+ facility_str=log_types[facility].facility_name;
+
+ snprintf(log_fmt_buf, MAX_ERROR_STRING_SIZE, "(%s/%s) %s",
+ facility_str,level_str,format);
+
+ log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
+ fmt_str=log_fmt_buf;
+ }
+
+ for(i=0; i<LOG_NUM_DESTINATIONS; i++){
+ if(r_logging_dest(i,facility,level)){
+ // Some platforms do not react well when you use a va_list more than
+ // once
+ va_list copy;
+ va_copy(copy, ap);
+ log_destinations[i].dest_vlog(facility,level,fmt_str,copy);
+ va_end(copy);
+ }
+ }
+ return(0);
+ }
+
+int stderr_vlog(int facility,int level,const char *format,va_list ap)
+ {
+#if 0 /* remove time stamping, for now */
+ char cbuf[30];
+ time_t tt;
+
+ tt=time(0);
+
+ ctime_r(&tt,cbuf);
+ cbuf[strlen(cbuf)-1]=0;
+
+ fprintf(stderr,"%s: ",cbuf);
+#endif
+
+ vfprintf(stderr,format,ap);
+ fprintf(stderr,"\n");
+ return(0);
+ }
+
+int syslog_vlog(int facility,int level,const char *format,va_list ap)
+ {
+#ifndef WIN32
+ vsyslog(level|LOG_LOCAL0,format,ap);
+#endif
+ return(0);
+ }
+
+int noop_vlog(int facility,int level,const char *format,va_list ap)
+ {
+ return(0);
+ }
+
+int r_log_e(int facility,int level,const char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+ r_vlog_e(facility,level,format,ap);
+ va_end(ap);
+
+ return(0);
+ }
+
+int r_vlog_e(int facility,int level,const char *format,va_list ap)
+ {
+ char log_fmt_buf[MAX_ERROR_STRING_SIZE];
+ if(r_logging(facility,level)) {
+ int formatlen = strlen(format);
+
+ if(formatlen+2 > MAX_ERROR_STRING_SIZE)
+ return(1);
+
+ strncpy(log_fmt_buf, format, formatlen);
+ strcpy(&log_fmt_buf[formatlen], ": ");
+ snprintf(&log_fmt_buf[formatlen+2], MAX_ERROR_STRING_SIZE - formatlen - 2, "%s",
+#ifdef WIN32
+ strerror(WSAGetLastError()));
+#else
+ strerror(errno));
+#endif
+ log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
+
+ r_vlog(facility,level,log_fmt_buf,ap);
+ }
+ return(0);
+ }
+
+int r_log_nr(int facility,int level,int r,const char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+ r_vlog_nr(facility,level,r,format,ap);
+ va_end(ap);
+
+ return(0);
+ }
+
+int r_vlog_nr(int facility,int level,int r,const char *format,va_list ap)
+ {
+ char log_fmt_buf[MAX_ERROR_STRING_SIZE];
+ if(r_logging(facility,level)) {
+ int formatlen = strlen(format);
+
+ if(formatlen+2 > MAX_ERROR_STRING_SIZE)
+ return(1);
+ strncpy(log_fmt_buf, format, formatlen);
+ strcpy(&log_fmt_buf[formatlen], ": ");
+ snprintf(&log_fmt_buf[formatlen+2], MAX_ERROR_STRING_SIZE - formatlen - 2, "%s",
+ nr_strerror(r));
+
+ log_fmt_buf[MAX_ERROR_STRING_SIZE-1]=0;
+
+ r_vlog(facility,level,log_fmt_buf,ap);
+ }
+ return(0);
+ }
+
+static int r_logging_dest(int dest_index, int facility, int level)
+ {
+ int thresh;
+
+ _r_log_init(0);
+
+ if(!log_destinations[dest_index].enabled)
+ return(0);
+
+ if(level <= r_log_level_environment)
+ return(1);
+
+ if(r_log_initted<R_LOG_INITTED2)
+ return(level<=r_log_level);
+
+ if(facility < 0 || facility > log_type_ct)
+ thresh=r_log_level;
+ else{
+ if(log_types[facility].level[dest_index]==LOG_LEVEL_NONE)
+ return(0);
+
+ if(log_types[facility].level[dest_index]>=0)
+ thresh=log_types[facility].level[dest_index];
+ else if(log_destinations[dest_index].default_level!=LOG_LEVEL_UNDEFINED)
+ thresh=log_destinations[dest_index].default_level;
+ else
+ thresh=r_log_level;
+ }
+
+ if(level<=thresh)
+ return(1);
+
+ return(0);
+ }
+
+int r_logging(int facility, int level)
+ {
+ int i;
+
+ _r_log_init(0);
+
+ /* return 1 if logging is on for any dest */
+
+ for(i=0; i<LOG_NUM_DESTINATIONS; i++){
+ if(r_logging_dest(i,facility,level))
+ return(1);
+ }
+
+ return(0);
+ }
+
+
+static int r_log_get_default_level(void)
+ {
+ char *log;
+ int _status;
+
+ log=getenv("R_LOG_LEVEL");
+
+ if(log){
+ r_log_level=atoi(log);
+ r_log_level_environment=atoi(log);
+ }
+ else{
+ r_log_level=LOGGING_DEFAULT_LEVEL;
+ }
+
+ _status=0;
+ //abort:
+ return(_status);
+ }
+
+
+static int r_log_get_destinations(int usereg)
+ {
+ char *log;
+ int i;
+ int r,_status;
+
+ log=getenv("R_LOG_DESTINATION");
+ if(log){
+ for(i=0; i<LOG_NUM_DESTINATIONS; i++)
+ log_destinations[i].enabled=!strcmp(log,log_destinations[i].dest_name);
+ }
+ else if(usereg){
+ NR_registry reg_key;
+ int i;
+ int value;
+ char c;
+
+ /* Get the data out of the registry */
+ for(i=0; i<LOG_NUM_DESTINATIONS; i++){
+ /* set callback for default level */
+ if(snprintf(reg_key,sizeof(reg_key),"%s.%s.level",LOGGING_REG_PREFIX,
+ log_destinations[i].dest_name)>=sizeof(reg_key))
+ ABORT(R_INTERNAL);
+
+ NR_reg_register_callback(reg_key,
+ NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE|NR_REG_CB_ACTION_DELETE,
+ r_log_default_level_change_cb,0);
+
+ if(r=r_log_get_reg_level(reg_key,&value)){
+ if(r==R_NOT_FOUND)
+ log_destinations[i].default_level=LOG_LEVEL_UNDEFINED;
+ else
+ ABORT(R_INTERNAL);
+ }
+ else
+ log_destinations[i].default_level=value;
+
+ /* set callback for the enabled key for this logging dest */
+ if(snprintf(reg_key,sizeof(reg_key),"%s.%s.enabled",LOGGING_REG_PREFIX,
+ log_destinations[i].dest_name)>=sizeof(reg_key))
+ ABORT(R_INTERNAL);
+
+ NR_reg_register_callback(reg_key,
+ NR_REG_CB_ACTION_ADD|NR_REG_CB_ACTION_CHANGE|NR_REG_CB_ACTION_DELETE,
+ r_log_destination_change_cb,0);
+
+ if(r=NR_reg_get_char(reg_key,&c)){
+ if(r==R_NOT_FOUND)
+ log_destinations[i].enabled=0;
+ else
+ ABORT(r);
+ }
+ else
+ log_destinations[i].enabled=c;
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static void r_log_destination_change_cb(void *cb_arg, char action, NR_registry name)
+ {
+ r_log_get_destinations(1);
+ }
+
+static void r_log_default_level_change_cb(void *cb_arg, char action, NR_registry name)
+ {
+ r_log_get_destinations(1);
+ }
+
+
+int r_log_init()
+ {
+ _r_log_init(1);
+
+ return 0;
+ }
+
+int _r_log_init(int use_reg)
+ {
+#ifndef WIN32
+ char *log;
+#endif
+
+ if(!use_reg){
+ if(r_log_initted<R_LOG_INITTED1){
+ r_log_get_default_level();
+ r_log_get_destinations(0);
+
+ r_log_initted=R_LOG_INITTED1;
+ }
+ }
+ else{
+ if(r_log_initted<R_LOG_INITTED2){
+ int facility;
+
+ r_log_get_default_level();
+ r_log_get_destinations(1);
+
+ r_log_register("generic",&facility);
+ r_log_register("logging",&NR_LOG_LOGGING);
+
+ r_log_initted=R_LOG_INITTED2;
+ }
+ }
+
+#ifdef WIN32
+ r_log_env_verbose=1;
+#else
+ log=getenv("R_LOG_VERBOSE");
+ if(log)
+ r_log_env_verbose=atoi(log);
+#endif
+
+ return(0);
+ }
+
+int r_log_set_extra_destination(int default_level, r_dest_vlog *dest_vlog)
+ {
+ int i;
+ log_destination *dest = 0;
+
+ for(i=0; i<LOG_NUM_DESTINATIONS; i++){
+ if(!strcmp("extra",log_destinations[i].dest_name)){
+ dest=&log_destinations[i];
+ break;
+ }
+ }
+
+ if(!dest)
+ return(R_INTERNAL);
+
+ if (dest_vlog==0){
+ dest->enabled=0;
+ dest->dest_vlog=noop_vlog;
+ }
+ else{
+ dest->enabled=1;
+ dest->default_level=default_level;
+ dest->dest_vlog=dest_vlog;
+ }
+
+ return(0);
+ }
+
diff --git a/media/mtransport/third_party/nrappkit/src/log/r_log.h b/media/mtransport/third_party/nrappkit/src/log/r_log.h
new file mode 100644
index 000000000..a72dfa066
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/log/r_log.h
@@ -0,0 +1,85 @@
+/**
+ r_log.h
+
+
+ Copyright (C) 2001, RTFM, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 3 15:14:45 2001
+ */
+
+
+#ifndef _r_log_h
+#define _r_log_h
+
+#ifndef WIN32
+#include <syslog.h>
+#endif
+#include <stdarg.h>
+#include <r_common.h>
+
+int r_log(int facility,int level,const char *fmt,...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+;
+
+int r_vlog(int facility,int level,const char *fmt,va_list ap);
+int r_dump(int facility,int level,char *name,char *data,int len);
+
+int r_log_e(int facility,int level,const char *fmt,...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+;
+
+int r_vlog_e(int facility,int level,const char *fmt,va_list ap);
+int r_log_nr(int facility,int level,int r,const char *fmt,...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 4, 5)))
+#endif
+;
+
+int r_vlog_nr(int facility,int level,int r,const char *fmt,va_list ap);
+
+int r_log_register(char *tipename,int *facility);
+int r_log_facility(int facility,char **tipename);
+int r_logging(int facility, int level);
+int r_log_init(void);
+
+#define LOG_GENERIC 0
+#define LOG_COMMON 0
+
+typedef int r_dest_vlog(int facility,int level,const char *format,va_list ap);
+int r_log_set_extra_destination(int default_level, r_dest_vlog *dest_vlog);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/plugin/nr_plugin.h b/media/mtransport/third_party/nrappkit/src/plugin/nr_plugin.h
new file mode 100644
index 000000000..56da0624a
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/plugin/nr_plugin.h
@@ -0,0 +1,57 @@
+/**
+ nr_plugin.h
+
+
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@networkresonance.com Mon Jun 19 18:18:54 2006
+ */
+
+
+#ifndef _nr_plugin_h
+#define _nr_plugin_h
+
+typedef int (NR_plugin_hook)(void);
+
+typedef struct NR_plugin_hook_def_ {
+ char *type;
+ NR_plugin_hook *func;
+} NR_plugin_hook_def;
+
+typedef struct NR_plugin_def_ {
+ int api_version; // Should be 1
+ char *name;
+ char *version;
+ NR_plugin_hook_def *hooks;
+} NR_plugin_def;
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/android/include/android_funcs.h b/media/mtransport/third_party/nrappkit/src/port/android/include/android_funcs.h
new file mode 100644
index 000000000..d48bbe137
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/android/include/android_funcs.h
@@ -0,0 +1,62 @@
+/**
+ linux_funcs.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 13 16:28:22 2004
+ */
+
+
+#ifndef _android_funcs_h
+#define _android_funcs_h
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ETHERTYPE_VLAN 0x8100
+
+#define STDIO_BYTES_BUFFERED(fp) (fp->_IO_read_end - fp->_IO_read_ptr)
+
+size_t strlcat(char *dst, const char *src, size_t siz);
+#ifndef strlcpy
+#define strlcpy(a,b,c) \
+ (strncpy((a),(b),(c)), \
+ ((c)<= 0 ? 0 : ((a)[(c)-1]='\0')), \
+ strlen((b)))
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/android/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/android/include/csi_platform.h
new file mode 100644
index 000000000..bcfb2bce7
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/android/include/csi_platform.h
@@ -0,0 +1,55 @@
+/**
+ platform.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 13 17:26:51 2004
+ */
+
+
+#ifndef _platform_h
+#define _platform_h
+
+#include <android_funcs.h>
+
+#ifdef NR_SOCKET_IS_VOID_PTR
+typedef void* NR_SOCKET;
+#else
+typedef int NR_SOCKET;
+#define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
+#define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
+#define NR_SOCKET_CLOSE(sock) close(sock)
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/android/include/sys/ttycom.h b/media/mtransport/third_party/nrappkit/src/port/android/include/sys/ttycom.h
new file mode 100644
index 000000000..852bf9103
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/android/include/sys/ttycom.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __ANDROID_TTYCOM_H
+#define __ANDROID_TTYCOM_H
+
+#include <asm/ioctls.h>
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/port/android/port-impl.mk b/media/mtransport/third_party/nrappkit/src/port/android/port-impl.mk
new file mode 100644
index 000000000..6704cfedf
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/android/port-impl.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2006, Network Resonance, Inc.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Network Resonance, Inc. nor the name of any
+# contributors to this software may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#EXTATTR_IMPL=xattr
diff --git a/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h
new file mode 100644
index 000000000..41f1a5b09
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h
@@ -0,0 +1,57 @@
+/**
+ platform.h
+
+
+ Copyright (C) 2005, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@network-resonance.com Tue Mar 15 14:28:12 PST 2005
+ */
+
+
+#ifndef _platform_h
+#define _platform_h
+
+#include <unistd.h>
+
+#define STDIO_BYTES_BUFFERED(fp) (fp->_r)
+
+#ifdef NR_SOCKET_IS_VOID_PTR
+typedef void* NR_SOCKET;
+#else
+typedef int NR_SOCKET;
+#define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
+#define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
+#define NR_SOCKET_CLOSE(sock) close(sock)
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/generic/include/sys/queue.h b/media/mtransport/third_party/nrappkit/src/port/generic/include/sys/queue.h
new file mode 100644
index 000000000..4d7b998a3
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/generic/include/sys/queue.h
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.58 2004/04/07 04:19:49 imp Exp $
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#include <stddef.h>
+
+#ifndef offsetof
+#define offsetof(type, field) ((size_t)(&((type *)0)->field))
+#endif
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+#define QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ char * lastfile;
+ int lastline;
+ char * prevfile;
+ int prevline;
+};
+
+#define TRACEBUF struct qm_trace trace;
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#define QMD_TRACE_ELEM(elem)
+#define QMD_TRACE_HEAD(head)
+#define TRACEBUF
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_NEXT(curelm, field) = \
+ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
+ } \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ if ((STAILQ_NEXT(curelm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+ } \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
+ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT((elm)->field.tqe_next); \
+ TRASHIT((elm)->field.tqe_prev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+struct quehead {
+ struct quehead *qh_link;
+ struct quehead *qh_rlink;
+};
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+static __inline void
+insque(void *a, void *b)
+{
+ struct quehead *element = (struct quehead *)a,
+ *head = (struct quehead *)b;
+
+ element->qh_link = head->qh_link;
+ element->qh_rlink = head;
+ head->qh_link = element;
+ element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+ struct quehead *element = (struct quehead *)a;
+
+ element->qh_link->qh_rlink = element->qh_rlink;
+ element->qh_rlink->qh_link = element->qh_link;
+ element->qh_rlink = 0;
+}
+
+#else /* !(__GNUC__ || __INTEL_COMPILER) */
+
+void insque(void *a, void *b);
+void remque(void *a);
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h
new file mode 100644
index 000000000..8aefaf924
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h
@@ -0,0 +1,55 @@
+/**
+ platform.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 13 17:26:51 2004
+ */
+
+
+#ifndef _platform_h
+#define _platform_h
+
+#include <linux_funcs.h>
+
+#ifdef NR_SOCKET_IS_VOID_PTR
+typedef void* NR_SOCKET;
+#else
+typedef int NR_SOCKET;
+#define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
+#define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
+#define NR_SOCKET_CLOSE(sock) close(sock)
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/linux/include/linux_funcs.h b/media/mtransport/third_party/nrappkit/src/port/linux/include/linux_funcs.h
new file mode 100644
index 000000000..161913630
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/linux/include/linux_funcs.h
@@ -0,0 +1,62 @@
+/**
+ linux_funcs.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 13 16:28:22 2004
+ */
+
+
+#ifndef _linux_funcs_h
+#define _linux_funcs_h
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ETHERTYPE_VLAN 0x8100
+
+#define STDIO_BYTES_BUFFERED(fp) (fp->_IO_read_end - fp->_IO_read_ptr)
+
+size_t strlcat(char *dst, const char *src, size_t siz);
+#ifndef strlcpy
+#define strlcpy(a,b,c) \
+ (strncpy((a),(b),(c)), \
+ ((c)<= 0 ? 0 : ((a)[(c)-1]='\0')), \
+ strlen((b)))
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/port/linux/include/sys/ttycom.h b/media/mtransport/third_party/nrappkit/src/port/linux/include/sys/ttycom.h
new file mode 100644
index 000000000..6f8a3066d
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/linux/include/sys/ttycom.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __LINUX_TTYCOM_H
+#define __LINUX_TTYCOM_H
+
+#include <asm/ioctls.h>
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/port/linux/port-impl.mk b/media/mtransport/third_party/nrappkit/src/port/linux/port-impl.mk
new file mode 100644
index 000000000..6704cfedf
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/linux/port-impl.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2006, Network Resonance, Inc.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Network Resonance, Inc. nor the name of any
+# contributors to this software may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+#EXTATTR_IMPL=xattr
diff --git a/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h
new file mode 100644
index 000000000..27c64c53d
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h
@@ -0,0 +1,107 @@
+/**
+ platform.h
+
+
+ Copyright (C) 2005, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@network-resonance.com Tue Mar 15 14:28:12 PST 2005
+ */
+
+
+#ifndef _csi_platform_h
+#define _csi_platform_h
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400 // This prevents weird "'TryEnterCriticalSection': identifier not found"
+ // compiler errors when poco/win32_mutex.h is included
+#endif
+
+#define UINT8 UBLAH_IGNORE_ME_PLEASE
+#define INT8 BLAH_IGNORE_ME_PLEASE
+#include <winsock2.h>
+#undef UINT8
+#undef INT8
+#include <r_types.h>
+#include <errno.h>
+
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+
+#define strcasestr stristr
+
+/* Hack version of strlcpy (in util/util.c) */
+size_t strlcat(char *dst, const char *src, size_t siz);
+
+/* Hack version of getopt() (in util/getopt.c) */
+int getopt(int argc, char *argv[], char *opstring);
+extern char *optarg;
+extern int optind;
+extern int opterr;
+
+/* Hack version of gettimeofday() (in util/util.c) */
+int gettimeofday(struct timeval *tv, void *tz);
+
+#ifdef NR_SOCKET_IS_VOID_PTR
+typedef void* NR_SOCKET;
+#else
+typedef SOCKET NR_SOCKET;
+#define NR_SOCKET_READ(sock,buf,count) recv((sock),(buf),(count),0)
+#define NR_SOCKET_WRITE(sock,buf,count) send((sock),(buf),(count),0)
+#define NR_SOCKET_CLOSE(sock) closesocket(sock)
+#endif
+
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+// Until we refine the Windows port....
+
+#define in_addr_t UINT4
+
+#ifndef strlcpy
+#define strlcpy(a,b,c) \
+ (strncpy((a),(b),(c)), \
+ ((c)<= 0 ? 0 : ((a)[(c)-1]='\0')), \
+ strlen((b)))
+#endif
+
+#endif /* _csi_platform_h */
+
diff --git a/media/mtransport/third_party/nrappkit/src/registry/c2ru.c b/media/mtransport/third_party/nrappkit/src/registry/c2ru.c
new file mode 100644
index 000000000..f2c19cb80
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/c2ru.c
@@ -0,0 +1,320 @@
+/*
+ *
+ * c2ru.c
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/c2ru.c,v $
+ * $Revision: 1.3 $
+ * $Date: 2007/06/26 22:37:50 $
+ *
+ * c2r utility methods
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#include <sys/queue.h>
+#include <string.h>
+#include <registry.h>
+#include "nr_common.h"
+#include <r_errors.h>
+#include <r_macros.h>
+#include <ctype.h>
+#include "c2ru.h"
+
+
+#define NRGET(func, type, get) \
+int \
+func(NR_registry parent, char *child, type **out) \
+{ \
+ int r, _status; \
+ NR_registry registry; \
+ type tmp; \
+ \
+ if ((r = nr_c2ru_make_registry(parent, child, registry))) \
+ ABORT(r); \
+ \
+ if ((r = get(registry, &tmp))) { \
+ if (r != R_NOT_FOUND) \
+ ABORT(r); \
+ *out = 0; \
+ } \
+ else { \
+ *out = RCALLOC(sizeof(tmp)); \
+ if (*out == 0) \
+ ABORT(R_NO_MEMORY); \
+ **out = tmp; \
+ } \
+ \
+ _status = 0; \
+abort: \
+ return (_status); \
+}
+
+int
+nr_c2ru_get_char(NR_registry parent, char *child, char **out)
+{
+ int r, _status;
+ NR_registry registry;
+ char tmp;
+
+ if ((r = nr_c2ru_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ if ((r = NR_reg_get_char(registry, &tmp))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ *out = 0;
+ }
+ else {
+ *out = RCALLOC(sizeof(tmp));
+ if (*out == 0)
+ ABORT(R_NO_MEMORY);
+ **out = tmp;
+ }
+
+ _status = 0;
+abort:
+ return (_status);
+}
+NRGET(nr_c2ru_get_uchar, UCHAR, NR_reg_get_uchar)
+NRGET(nr_c2ru_get_int2, INT2, NR_reg_get_int2)
+NRGET(nr_c2ru_get_uint2, UINT2, NR_reg_get_uint2)
+NRGET(nr_c2ru_get_int4, INT4, NR_reg_get_int4)
+NRGET(nr_c2ru_get_uint4, UINT4, NR_reg_get_uint4)
+NRGET(nr_c2ru_get_int8, INT8, NR_reg_get_int8)
+NRGET(nr_c2ru_get_uint8, UINT8, NR_reg_get_uint8)
+NRGET(nr_c2ru_get_double, double, NR_reg_get_double)
+NRGET(nr_c2ru_get_string, char*, NR_reg_alloc_string)
+NRGET(nr_c2ru_get_data, Data, NR_reg_alloc_data)
+
+
+#define NRSET(func, type, set) \
+int \
+func(NR_registry parent, char *child, type *in) \
+{ \
+ int r, _status; \
+ NR_registry registry; \
+ \
+ if (in == 0) \
+ return 0; \
+ \
+ if ((r = nr_c2ru_make_registry(parent, child, registry))) \
+ ABORT(r); \
+ \
+ if ((r = set(registry, *in))) \
+ ABORT(r); \
+ \
+ _status = 0; \
+abort: \
+ return (_status); \
+}
+
+NRSET(nr_c2ru_set_char, char, NR_reg_set_char)
+NRSET(nr_c2ru_set_uchar, UCHAR, NR_reg_set_uchar)
+NRSET(nr_c2ru_set_int2, INT2, NR_reg_set_int2)
+NRSET(nr_c2ru_set_uint2, UINT2, NR_reg_set_uint2)
+NRSET(nr_c2ru_set_int4, INT4, NR_reg_set_int4)
+NRSET(nr_c2ru_set_uint4, UINT4, NR_reg_set_uint4)
+NRSET(nr_c2ru_set_int8, INT8, NR_reg_set_int8)
+NRSET(nr_c2ru_set_uint8, UINT8, NR_reg_set_uint8)
+NRSET(nr_c2ru_set_double, double, NR_reg_set_double)
+NRSET(nr_c2ru_set_string, char*, NR_reg_set_string)
+
+int
+nr_c2ru_set_data(NR_registry parent, char *child, Data *in)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if (in == 0)
+ return 0;
+
+ if ((r = nr_c2ru_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ if ((r = NR_reg_set_bytes(registry, in->data, in->len)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+#define NRFREE(func, type) \
+int \
+func(type *in) \
+{ \
+ if (in) \
+ RFREE(in); \
+ return 0; \
+}
+
+NRFREE(nr_c2ru_free_char, char)
+NRFREE(nr_c2ru_free_uchar, UCHAR)
+NRFREE(nr_c2ru_free_int2, INT2)
+NRFREE(nr_c2ru_free_uint2, UINT2)
+NRFREE(nr_c2ru_free_int4, INT4)
+NRFREE(nr_c2ru_free_uint4, UINT4)
+NRFREE(nr_c2ru_free_int8, INT8)
+NRFREE(nr_c2ru_free_uint8, UINT8)
+NRFREE(nr_c2ru_free_double, double)
+
+
+int
+nr_c2ru_free_string(char **in)
+{
+ if (*in)
+ RFREE(*in);
+ if (in)
+ RFREE(in);
+ return 0;
+}
+
+int
+nr_c2ru_free_data(Data *in)
+{
+ int r, _status;
+
+ if (in) {
+ if ((r=r_data_destroy(&in)))
+ ABORT(r);
+ }
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+int
+nr_c2ru_get_children(NR_registry parent, char *child, void *ptr, size_t size, int (*get)(NR_registry, void*))
+{
+ int r, _status;
+ NR_registry registry;
+ unsigned int count;
+ int i;
+ NR_registry name;
+ struct entry { TAILQ_ENTRY(entry) entries; } *entry;
+ TAILQ_HEAD(, entry) *tailq = (void*)ptr;
+
+ TAILQ_INIT(tailq);
+
+ if ((r=nr_c2ru_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ if ((r=NR_reg_get_child_count(registry, &count))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+ else {
+ for (i = 0; i < count; ++i) {
+ if ((r=NR_reg_get_child_registry(registry, i, name))) {
+ /* ignore R_NOT_FOUND errors */
+ if (r == R_NOT_FOUND)
+ continue;
+ else
+ ABORT(r);
+ }
+
+ if ((r=get(name, &entry))) {
+ /* ignore R_NOT_FOUND errors */
+ if (r == R_NOT_FOUND)
+ continue;
+ else
+ ABORT(r);
+ }
+
+ TAILQ_INSERT_TAIL(tailq, entry, entries);
+ }
+ }
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+int
+nr_c2ru_set_children(NR_registry parent, char *child, void *ptr, int (*set)(NR_registry, void*), int (*label)(NR_registry, void*, char[NR_REG_MAX_NR_REGISTRY_LEN]))
+{
+ int r, _status;
+ NR_registry registry;
+ int i;
+ NR_registry name;
+ char buffer[NR_REG_MAX_NR_REGISTRY_LEN];
+ struct entry { TAILQ_ENTRY(entry) entries; } *entry;
+ TAILQ_HEAD(, entry) *tailq = (void*)ptr;
+
+ if ((r=nr_c2ru_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ (void)NR_reg_del(registry);
+
+ i = 0;
+ TAILQ_FOREACH(entry, tailq, entries) {
+ if (label == 0 || (r=label(registry, entry, buffer))) {
+ snprintf(buffer, sizeof(buffer), "%d", i);
+ }
+ if ((r=nr_c2ru_make_registry(registry, buffer, name)))
+ ABORT(r);
+
+ if ((r=set(name, entry)))
+ ABORT(r);
+
+ ++i;
+ }
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+int
+nr_c2ru_free_children(void *ptr, int (*free)(void*))
+{
+ struct entry { TAILQ_ENTRY(entry) entries; } *entry;
+ TAILQ_HEAD(, entry) *tailq = (void*)ptr;
+
+ while (! TAILQ_EMPTY(tailq)) {
+ entry = TAILQ_FIRST(tailq);
+ TAILQ_REMOVE(tailq, entry, entries);
+ (void)free(entry);
+ }
+
+ return 0;
+}
+
+/* requires parent already in legal form */
+int
+nr_c2ru_make_registry(NR_registry parent, char *child, NR_registry out)
+{
+ return NR_reg_make_registry(parent, child, out);
+}
diff --git a/media/mtransport/third_party/nrappkit/src/registry/c2ru.h b/media/mtransport/third_party/nrappkit/src/registry/c2ru.h
new file mode 100644
index 000000000..0f8c38ecc
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/c2ru.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * c2ru.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/c2ru.h,v $
+ * $Revision: 1.2 $
+ * $Date: 2006/08/16 19:39:13 $
+ *
+ * c2r utility methods
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __C2RU_H__
+#define __C2RU_H__
+
+#include <sys/types.h>
+#include <r_types.h>
+#include <r_data.h>
+#include "registry_int.h"
+
+int nr_c2ru_get_char(NR_registry parent, char *child, char **out);
+int nr_c2ru_get_uchar(NR_registry parent, char *child, UCHAR **out);
+int nr_c2ru_get_int2(NR_registry parent, char *child, INT2 **out);
+int nr_c2ru_get_uint2(NR_registry parent, char *child, UINT2 **out);
+int nr_c2ru_get_int4(NR_registry parent, char *child, INT4 **out);
+int nr_c2ru_get_uint4(NR_registry parent, char *child, UINT4 **out);
+int nr_c2ru_get_int8(NR_registry parent, char *child, INT8 **out);
+int nr_c2ru_get_uint8(NR_registry parent, char *child, UINT8 **out);
+int nr_c2ru_get_double(NR_registry parent, char *child, double **out);
+int nr_c2ru_get_data(NR_registry parent, char *child, Data **out);
+int nr_c2ru_get_string(NR_registry parent, char *child, char ***out);
+
+int nr_c2ru_set_char(NR_registry parent, char *child, char *data);
+int nr_c2ru_set_uchar(NR_registry parent, char *child, UCHAR *data);
+int nr_c2ru_set_int2(NR_registry parent, char *child, INT2 *data);
+int nr_c2ru_set_uint2(NR_registry parent, char *child, UINT2 *data);
+int nr_c2ru_set_int4(NR_registry parent, char *child, INT4 *data);
+int nr_c2ru_set_uint4(NR_registry parent, char *child, UINT4 *data);
+int nr_c2ru_set_int8(NR_registry parent, char *child, INT8 *data);
+int nr_c2ru_set_uint8(NR_registry parent, char *child, UINT8 *data);
+int nr_c2ru_set_double(NR_registry parent, char *child, double *data);
+int nr_c2ru_set_registry(NR_registry parent, char *child);
+int nr_c2ru_set_data(NR_registry parent, char *child, Data *data);
+int nr_c2ru_set_string(NR_registry parent, char *child, char **data);
+
+int nr_c2ru_free_char(char *data);
+int nr_c2ru_free_uchar(UCHAR *data);
+int nr_c2ru_free_int2(INT2 *data);
+int nr_c2ru_free_uint2(UINT2 *data);
+int nr_c2ru_free_int4(INT4 *data);
+int nr_c2ru_free_uint4(UINT4 *data);
+int nr_c2ru_free_int8(INT8 *data);
+int nr_c2ru_free_uint8(UINT8 *data);
+int nr_c2ru_free_double(double *data);
+int nr_c2ru_free_data(Data *data);
+int nr_c2ru_free_string(char **data);
+
+int nr_c2ru_get_children(NR_registry parent, char *child, void *ptr, size_t size, int (*get)(NR_registry, void*));
+int nr_c2ru_set_children(NR_registry parent, char *child, void *ptr, int (*set)(NR_registry, void*), int (*label)(NR_registry, void*, char[NR_REG_MAX_NR_REGISTRY_LEN]));
+int nr_c2ru_free_children(void *ptr, int (*free)(void*));
+
+int nr_c2ru_make_registry(NR_registry parent, char *child, NR_registry out);
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry.c b/media/mtransport/third_party/nrappkit/src/registry/registry.c
new file mode 100644
index 000000000..d7ba472e5
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registry.c
@@ -0,0 +1,604 @@
+/*
+ *
+ * registry.c
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $
+ * $Revision: 1.6 $
+ * $Date: 2007/11/21 00:09:12 $
+ *
+ * Datastore for tracking configuration and related info.
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#ifndef _MSC_VER
+#include <strings.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#endif
+#ifdef OPENSSL
+#include <openssl/ssl.h>
+#endif
+#include <ctype.h>
+#include "registry.h"
+#include "registry_int.h"
+#include "registry_vtbl.h"
+#include "r_assoc.h"
+#include "nr_common.h"
+#include "r_log.h"
+#include "r_errors.h"
+#include "r_macros.h"
+#include "c2ru.h"
+
+/* vtbl used to switch hit between local and remote invocations */
+static nr_registry_module *reg_vtbl = 0;
+
+/* must be in the order the types are numbered */
+static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" };
+
+int NR_LOG_REGISTRY=0;
+
+NR_registry NR_TOP_LEVEL_REGISTRY = "";
+
+int
+NR_reg_init(void *mode)
+{
+ int r, _status;
+ nr_registry_module *module = (nr_registry_module*)mode;
+#ifdef SANITY_CHECKS
+ NR_registry registry;
+#endif
+
+ if (reg_vtbl) {
+ if (reg_vtbl != module) {
+ r_log(LOG_GENERIC,LOG_ERR,"Can't reinitialize registry in different mode");
+ ABORT(R_INTERNAL);
+ }
+
+ return(0);
+ }
+
+ reg_vtbl = module;
+
+ if ((r=reg_vtbl->vtbl->init(mode)))
+ ABORT(r);
+
+#ifdef SANITY_CHECKS
+ if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry)))
+ ABORT(r);
+ assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0);
+#endif
+
+ r_log_init();
+ r_log_register("registry",&NR_LOG_REGISTRY);
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY,
+ (_status ? LOG_ERR : LOG_INFO),
+ (_status ? "Couldn't initialize registry" : "Initialized registry"));
+ return(_status);
+}
+
+int
+NR_reg_initted(void)
+{
+ return reg_vtbl!=0;
+}
+
+#define NRREGGET(func, method, type) \
+int \
+func(NR_registry name, type *out) \
+{ \
+ return reg_vtbl->vtbl->method(name, out); \
+}
+
+NRREGGET(NR_reg_get_char, get_char, char)
+NRREGGET(NR_reg_get_uchar, get_uchar, UCHAR)
+NRREGGET(NR_reg_get_int2, get_int2, INT2)
+NRREGGET(NR_reg_get_uint2, get_uint2, UINT2)
+NRREGGET(NR_reg_get_int4, get_int4, INT4)
+NRREGGET(NR_reg_get_uint4, get_uint4, UINT4)
+NRREGGET(NR_reg_get_int8, get_int8, INT8)
+NRREGGET(NR_reg_get_uint8, get_uint8, UINT8)
+NRREGGET(NR_reg_get_double, get_double, double)
+
+int
+NR_reg_get_registry(NR_registry name, NR_registry out)
+{
+ return reg_vtbl->vtbl->get_registry(name, out);
+}
+
+int
+NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
+{
+ return reg_vtbl->vtbl->get_bytes(name, out, size, length);
+}
+
+int
+NR_reg_get_string(NR_registry name, char *out, size_t size)
+{
+ return reg_vtbl->vtbl->get_string(name, out, size);
+}
+
+int
+NR_reg_get_length(NR_registry name, size_t *length)
+{
+ return reg_vtbl->vtbl->get_length(name, length);
+}
+
+int
+NR_reg_get_type(NR_registry name, NR_registry_type type)
+{
+ return reg_vtbl->vtbl->get_type(name, type);
+}
+
+#define NRREGSET(func, method, type) \
+int \
+func(NR_registry name, type data) \
+{ \
+ return reg_vtbl->vtbl->method(name, data); \
+}
+
+NRREGSET(NR_reg_set_char, set_char, char)
+NRREGSET(NR_reg_set_uchar, set_uchar, UCHAR)
+NRREGSET(NR_reg_set_int2, set_int2, INT2)
+NRREGSET(NR_reg_set_uint2, set_uint2, UINT2)
+NRREGSET(NR_reg_set_int4, set_int4, INT4)
+NRREGSET(NR_reg_set_uint4, set_uint4, UINT4)
+NRREGSET(NR_reg_set_int8, set_int8, INT8)
+NRREGSET(NR_reg_set_uint8, set_uint8, UINT8)
+NRREGSET(NR_reg_set_double, set_double, double)
+NRREGSET(NR_reg_set_string, set_string, char*)
+
+int
+NR_reg_set_registry(NR_registry name)
+{
+ return reg_vtbl->vtbl->set_registry(name);
+}
+
+int
+NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length)
+{
+ return reg_vtbl->vtbl->set_bytes(name, data, length);
+}
+
+
+int
+NR_reg_del(NR_registry name)
+{
+ return reg_vtbl->vtbl->del(name);
+}
+
+int
+NR_reg_fin(NR_registry name)
+{
+ return reg_vtbl->vtbl->fin(name);
+}
+
+int
+NR_reg_get_child_count(char *parent, unsigned int *count)
+{
+ assert(sizeof(count) == sizeof(size_t));
+ return reg_vtbl->vtbl->get_child_count(parent, (size_t*)count);
+}
+
+int
+NR_reg_get_child_registry(char *parent, unsigned int i, NR_registry child)
+{
+ int r, _status;
+ size_t count;
+ NR_registry *children=0;
+
+ if ((r=reg_vtbl->vtbl->get_child_count(parent, &count)))
+ ABORT(r);
+
+ if (i >= count)
+ ABORT(R_NOT_FOUND);
+ else {
+ count++;
+ children = (NR_registry *)RCALLOC(count * sizeof(NR_registry));
+ if (!children)
+ ABORT(R_NO_MEMORY);
+
+ if ((r=reg_vtbl->vtbl->get_children(parent, children, count, &count)))
+ ABORT(r);
+
+ if (i >= count)
+ ABORT(R_NOT_FOUND);
+
+ strncpy(child, children[i], sizeof(NR_registry));
+ }
+
+ _status=0;
+ abort:
+ RFREE(children);
+ return(_status);
+}
+
+int
+NR_reg_get_children(NR_registry parent, NR_registry *children, size_t size, size_t *length)
+{
+ return reg_vtbl->vtbl->get_children(parent, children, size, length);
+}
+
+int
+NR_reg_dump()
+{
+ int r, _status;
+
+ if ((r=reg_vtbl->vtbl->dump(0)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+// convenience methods, call RFREE on the returned data
+int
+NR_reg_alloc_data(NR_registry name, Data *data)
+{
+ int r, _status;
+ size_t length;
+ UCHAR *tmp = 0;
+ size_t sanity_check;
+
+ if ((r=NR_reg_get_length(name, &length)))
+ ABORT(r);
+
+ if (!(tmp = (void*)RMALLOC(length)))
+ ABORT(R_NO_MEMORY);
+
+ if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check)))
+ ABORT(r);
+
+ assert(length == sanity_check);
+
+ data->len = length;
+ data->data = tmp;
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (tmp) RFREE(tmp);
+ }
+ return(_status);
+}
+
+int
+NR_reg_alloc_string(NR_registry name, char **data)
+{
+ int r, _status;
+ size_t length;
+ char *tmp = 0;
+
+ if ((r=NR_reg_get_length(name, &length)))
+ ABORT(r);
+
+ if (!(tmp = (void*)RMALLOC(length+1)))
+ ABORT(R_NO_MEMORY);
+
+ if ((r=NR_reg_get_string(name, tmp, length+1)))
+ ABORT(r);
+
+ assert(length == strlen(tmp));
+
+ *data = tmp;
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (tmp) RFREE(tmp);
+ }
+ return(_status);
+}
+
+
+char *
+nr_reg_type_name(int type)
+{
+ if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY))
+ return(NULL);
+
+ return(typenames[type]);
+}
+
+int
+nr_reg_compute_type(char *typename, int *type)
+{
+ int _status;
+ int i;
+
+#ifdef SANITY_CHECKS
+ assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string"));
+ assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry"));
+ assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1));
+#endif
+
+ for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) {
+ if (!strcasecmp(typenames[i], typename)) {
+ *type = i;
+ return 0;
+ }
+ }
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+/* More convenience functions: the same as their parents but they
+ take a prefix and a suffix */
+#define NRGET2(func, type, get) \
+int \
+func(NR_registry parent, char *child, type *out) \
+{ \
+ int r, _status; \
+ NR_registry registry; \
+ \
+ if ((r = NR_reg_make_registry(parent, child, registry))) \
+ ABORT(r); \
+ \
+ if ((r = get(registry, out))) { \
+ ABORT(r); \
+ } \
+ \
+ _status = 0; \
+abort: \
+ return (_status); \
+}
+
+NRGET2(NR_reg_get2_char, char, NR_reg_get_char)
+NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar)
+NRGET2(NR_reg_get2_int2, INT2, NR_reg_get_int2)
+NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2)
+NRGET2(NR_reg_get2_int4, INT4, NR_reg_get_int4)
+NRGET2(NR_reg_get2_uint4, UINT4, NR_reg_get_uint4)
+NRGET2(NR_reg_get2_int8, INT8, NR_reg_get_int8)
+NRGET2(NR_reg_get2_uint8, UINT8, NR_reg_get_uint8)
+NRGET2(NR_reg_get2_double, double, NR_reg_get_double)
+NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string)
+NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data)
+
+int
+NR_reg_get2_bytes(NR_registry parent, char *child, UCHAR *out, size_t size, size_t *length)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=NR_reg_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ if ((r=NR_reg_get_bytes(registry, out, size, length)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+int
+NR_reg_get2_string(NR_registry parent, char *child, char *out, size_t size)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=NR_reg_make_registry(parent, child, registry)))
+ ABORT(r);
+
+ if ((r=NR_reg_get_string(registry, out, size)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+/* More convenience functions: the same as their parents but they
+ take a prefix and a suffix */
+#define NRSET2(func, type, set) \
+int \
+func(NR_registry parent, char *child, type in) \
+{ \
+ int r, _status; \
+ NR_registry registry; \
+ \
+ if ((r = NR_reg_make_registry(parent, child, registry))) \
+ ABORT(r); \
+ \
+ if ((r = set(registry, in))) { \
+ ABORT(r); \
+ } \
+ \
+ _status = 0; \
+abort: \
+ return (_status); \
+}
+
+NRSET2(NR_reg_set2_char, char, NR_reg_set_char)
+NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar)
+NRSET2(NR_reg_set2_int2, INT2, NR_reg_set_int2)
+NRSET2(NR_reg_set2_uint2, UINT2, NR_reg_set_uint2)
+NRSET2(NR_reg_set2_int4, INT4, NR_reg_set_int4)
+NRSET2(NR_reg_set2_uint4, UINT4, NR_reg_set_uint4)
+NRSET2(NR_reg_set2_int8, INT8, NR_reg_set_int8)
+NRSET2(NR_reg_set2_uint8, UINT8, NR_reg_set_uint8)
+NRSET2(NR_reg_set2_double, double, NR_reg_set_double)
+NRSET2(NR_reg_set2_string, char*, NR_reg_set_string)
+
+int
+NR_reg_set2_bytes(NR_registry prefix, char *name, UCHAR *data, size_t length)
+{
+ int r, _status;
+ NR_registry registry;
+
+ if ((r = NR_reg_make_registry(prefix, name, registry)))
+ ABORT(r);
+
+ if ((r = NR_reg_set_bytes(registry, data, length)))
+ ABORT(r);
+
+ _status = 0;
+abort:
+ return (_status);
+}
+
+
+int
+NR_reg_make_child_registry(NR_registry parent, NR_registry descendant, unsigned int generation, NR_registry child)
+{
+ int _status;
+ size_t length;
+
+ length = strlen(parent);
+
+ if (strncasecmp(parent, descendant, length))
+ ABORT(R_BAD_ARGS);
+
+ while (descendant[length] != '\0') {
+ if (descendant[length] == '.') {
+ if (generation == 0)
+ break;
+
+ --generation;
+ }
+
+ ++length;
+ if (length >= sizeof(NR_registry))
+ ABORT(R_BAD_ARGS);
+ }
+
+ strncpy(child, descendant, length);
+ child[length] = '\0';
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+NR_reg_get2_child_count(NR_registry base, NR_registry name, unsigned int *count)
+ {
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=nr_c2ru_make_registry(base, name, registry)))
+ ABORT(r);
+
+ if (r=NR_reg_get_child_count(registry,count))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int
+NR_reg_get2_child_registry(NR_registry base, NR_registry name, unsigned int i, NR_registry child)
+ {
+ int r, _status;
+ NR_registry registry;
+
+ if ((r=nr_c2ru_make_registry(base, name, registry)))
+ ABORT(r);
+
+ if (r=NR_reg_get_child_registry(registry, i, child))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+
+/* requires parent already in legal form */
+int
+NR_reg_make_registry(NR_registry parent, char *child, NR_registry out)
+{
+ int r, _status;
+ int plen;
+ int clen;
+ char *c;
+ int i;
+
+ if ((r=nr_reg_is_valid(parent)))
+ ABORT(r);
+
+ if (*child == '.')
+ ABORT(R_BAD_ARGS);
+
+ clen = strlen(child);
+ if (!clen)
+ ABORT(R_BAD_ARGS);
+ plen = strlen(parent);
+ if ((plen + clen + 2) > sizeof(NR_registry))
+ ABORT(R_BAD_ARGS);
+
+ if (out != parent)
+ strcpy(out, parent);
+
+ c = &(out[plen]);
+
+ if (parent[0] != '\0') {
+ *c = '.';
+ ++c;
+ }
+
+ for (i = 0; i < clen; ++i, ++c) {
+ *c = child[i];
+ if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c))
+ *c = '_';
+ }
+
+ *c = '\0';
+
+ _status = 0;
+abort:
+ return _status;
+}
+
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry.h b/media/mtransport/third_party/nrappkit/src/registry/registry.h
new file mode 100644
index 000000000..b48893ba7
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registry.h
@@ -0,0 +1,154 @@
+/*
+ *
+ * registry.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.h,v $
+ * $Revision: 1.3 $
+ * $Date: 2007/07/17 17:58:16 $
+ *
+ * Datastore for tracking configuration and related info.
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __REGISTRY_H__
+#define __REGISTRY_H__
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <r_types.h>
+#include <r_data.h>
+
+#define NR_REG_MAX_NR_REGISTRY_LEN 128
+#define NR_REG_MAX_TYPE_LEN 32
+
+typedef char NR_registry[NR_REG_MAX_NR_REGISTRY_LEN];
+typedef char NR_registry_type[NR_REG_MAX_TYPE_LEN];
+
+extern NR_registry NR_TOP_LEVEL_REGISTRY;
+
+extern void *NR_REG_MODE_LOCAL;
+extern void *NR_REG_MODE_REMOTE;
+
+int NR_reg_init(void *mode);
+
+int NR_reg_initted(void);
+
+int NR_reg_get_char(NR_registry name, char *out);
+int NR_reg_get_uchar(NR_registry name, UCHAR *out);
+int NR_reg_get_int2(NR_registry name, INT2 *out);
+int NR_reg_get_uint2(NR_registry name, UINT2 *out);
+int NR_reg_get_int4(NR_registry name, INT4 *out);
+int NR_reg_get_uint4(NR_registry name, UINT4 *out);
+int NR_reg_get_int8(NR_registry name, INT8 *out);
+int NR_reg_get_uint8(NR_registry name, UINT8 *out);
+int NR_reg_get_double(NR_registry name, double *out);
+int NR_reg_get_registry(NR_registry name, NR_registry out);
+
+int NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length);
+int NR_reg_get_string(NR_registry name, char *out, size_t size);
+int NR_reg_get_length(NR_registry name, size_t *length);
+int NR_reg_get_type(NR_registry name, NR_registry_type type);
+
+
+int NR_reg_get2_char(NR_registry prefix, char *name, char *);
+int NR_reg_get2_uchar(NR_registry prefix, char *name, UCHAR *);
+int NR_reg_get2_int2(NR_registry prefix, char *name, INT2 *);
+int NR_reg_get2_uint2(NR_registry prefix, char *name, UINT2 *);
+int NR_reg_get2_int4(NR_registry prefix, char *name, INT4 *);
+int NR_reg_get2_uint4(NR_registry prefix, char *name, UINT4 *);
+int NR_reg_get2_int8(NR_registry prefix, char *name, INT8 *);
+int NR_reg_get2_uint8(NR_registry prefix, char *name, UINT8 *);
+int NR_reg_get2_double(NR_registry prefix, char *name, double *);
+int NR_reg_get2_bytes(NR_registry prefix, char *name, UCHAR *out, size_t size, size_t *length);
+int NR_reg_get2_string(NR_registry prefix, char *name, char *out, size_t size);
+
+int NR_reg_alloc2_string(NR_registry prefix, char *name, char **);
+int NR_reg_alloc2_data(NR_registry prefix, char *name, Data *);
+
+int NR_reg_set_char(NR_registry name, char data);
+int NR_reg_set_uchar(NR_registry name, UCHAR data);
+int NR_reg_set_int2(NR_registry name, INT2 data);
+int NR_reg_set_uint2(NR_registry name, UINT2 data);
+int NR_reg_set_int4(NR_registry name, INT4 data);
+int NR_reg_set_uint4(NR_registry name, UINT4 data);
+int NR_reg_set_int8(NR_registry name, INT8 data);
+int NR_reg_set_uint8(NR_registry name, UINT8 data);
+int NR_reg_set_double(NR_registry name, double data);
+
+int NR_reg_set_registry(NR_registry name);
+
+int NR_reg_set_bytes(NR_registry name, UCHAR *data, size_t length);
+int NR_reg_set_string(NR_registry name, char *data);
+
+int NR_reg_set2_char(NR_registry prefix, char *name, char data);
+int NR_reg_set2_uchar(NR_registry prefix, char *name, UCHAR data);
+int NR_reg_set2_int2(NR_registry prefix, char *name, INT2 data);
+int NR_reg_set2_uint2(NR_registry prefix, char *name, UINT2 data);
+int NR_reg_set2_int4(NR_registry prefix, char *name, INT4 data);
+int NR_reg_set2_uint4(NR_registry prefix, char *name, UINT4 data);
+int NR_reg_set2_int8(NR_registry prefix, char *name, INT8 data);
+int NR_reg_set2_uint8(NR_registry prefix, char *name, UINT8 data);
+int NR_reg_set2_double(NR_registry prefix, char *name, double data);
+
+int NR_reg_set2_bytes(NR_registry prefix, char *name, UCHAR *data, size_t length);
+int NR_reg_set2_string(NR_registry prefix, char *name, char *data);
+
+int NR_reg_del(NR_registry name);
+
+int NR_reg_fin(NR_registry name);
+
+int NR_reg_get_child_count(NR_registry parent, unsigned int *count);
+int NR_reg_get_child_registry(NR_registry parent, unsigned int i, NR_registry child);
+int NR_reg_get2_child_count(NR_registry base, NR_registry name, unsigned int *count);
+int NR_reg_get2_child_registry(NR_registry base, NR_registry name, unsigned int i, NR_registry child);
+int NR_reg_get_children(NR_registry parent, NR_registry children[], size_t size, size_t *length);
+
+int NR_reg_dump(void);
+
+/* convenience methods, call RFREE on the returned data */
+int NR_reg_alloc_data(NR_registry name, Data *data);
+int NR_reg_alloc_string(NR_registry name, char **data);
+
+#define NR_REG_CB_ACTION_ADD (1<<0)
+#define NR_REG_CB_ACTION_CHANGE (1<<1)
+#define NR_REG_CB_ACTION_DELETE (1<<2)
+#define NR_REG_CB_ACTION_FINAL (1<<6)
+int NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg);
+int NR_reg_unregister_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name));
+
+int NR_reg_make_registry(NR_registry parent, char *child, NR_registry out);
+int NR_reg_make_child_registry(NR_registry parent, NR_registry descendant, unsigned int generation, NR_registry child);
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry_int.h b/media/mtransport/third_party/nrappkit/src/registry/registry_int.h
new file mode 100644
index 000000000..d6d412c54
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registry_int.h
@@ -0,0 +1,97 @@
+#if 0
+#define NR_LOG_REGISTRY BLAHBLAH()
+#define LOG_REGISTRY BLAHBLAH()
+static int BLAHBLAH() {
+int blahblah;
+r_log_register("registry",&blahblah);
+return blahblah;
+}
+#endif
+
+/*
+ *
+ * registry_int.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_int.h,v $
+ * $Revision: 1.3 $
+ * $Date: 2007/06/26 22:37:51 $
+ *
+ * Callback-related functions
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __REGISTRY_INT_H__
+#define __REGISTRY_INT_H__
+
+#include <sys/types.h>
+#include <r_types.h>
+#ifndef NO_REG_RPC
+#include <rpc/rpc.h>
+#endif
+
+extern int NR_LOG_REGISTRY;
+
+int nr_reg_is_valid(NR_registry name);
+
+#define NR_REG_TYPE_CHAR 0
+#define NR_REG_TYPE_UCHAR 1
+#define NR_REG_TYPE_INT2 2
+#define NR_REG_TYPE_UINT2 3
+#define NR_REG_TYPE_INT4 4
+#define NR_REG_TYPE_UINT4 5
+#define NR_REG_TYPE_INT8 6
+#define NR_REG_TYPE_UINT8 7
+#define NR_REG_TYPE_DOUBLE 8
+#define NR_REG_TYPE_BYTES 9
+#define NR_REG_TYPE_STRING 10
+#define NR_REG_TYPE_REGISTRY 11
+char *nr_reg_type_name(int type);
+int nr_reg_compute_type(char *type_name, int *type);
+
+char *nr_reg_action_name(int action);
+
+int nr_reg_cb_init(void);
+int nr_reg_client_cb_init(void);
+int nr_reg_register_for_callbacks(int fd, int connect_to_port);
+int nr_reg_raise_event(NR_registry name, int action);
+#ifndef NO_REG_RPC
+int nr_reg_get_client(CLIENT **client);
+#endif
+
+#define CALLBACK_SERVER_ADDR "127.0.0.1"
+#define CALLBACK_SERVER_PORT 8082
+#define CALLBACK_SERVER_BACKLOG 32
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry_local.c b/media/mtransport/third_party/nrappkit/src/registry/registry_local.c
new file mode 100644
index 000000000..c52e22351
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registry_local.c
@@ -0,0 +1,1168 @@
+/*
+ *
+ * registry.c
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_local.c,v $
+ * $Revision: 1.4 $
+ * $Date: 2007/11/21 00:09:13 $
+ *
+ * Datastore for tracking configuration and related info.
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#ifndef WIN32
+#include <strings.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#endif
+#ifdef OPENSSL
+#include <openssl/ssl.h>
+#endif
+#include <ctype.h>
+#include "registry.h"
+#include "registry_int.h"
+#include "registry_vtbl.h"
+#include "r_assoc.h"
+#include "nr_common.h"
+#include "r_log.h"
+#include "r_errors.h"
+#include "r_macros.h"
+
+/* if C were an object-oriented language, nr_scalar_registry_node and
+ * nr_array_registry_node would subclass nr_registry_node, but it isn't
+ * object-oriented language, so this is used in cases where the pointer
+ * could be of either type */
+typedef struct nr_registry_node_ {
+ unsigned char type;
+} nr_registry_node;
+
+typedef struct nr_scalar_registry_node_ {
+ unsigned char type;
+ union {
+ char _char;
+ UCHAR _uchar;
+ INT2 _nr_int2;
+ UINT2 _nr_uint2;
+ INT4 _nr_int4;
+ UINT4 _nr_uint4;
+ INT8 _nr_int8;
+ UINT8 _nr_uint8;
+ double _double;
+ } scalar;
+} nr_scalar_registry_node;
+
+/* string, bytes */
+typedef struct nr_array_registry_node_ {
+ unsigned char type;
+ struct {
+ unsigned int length;
+ unsigned char data[1];
+ } array;
+} nr_array_registry_node;
+
+static int nr_reg_local_init(nr_registry_module *me);
+static int nr_reg_local_get_char(NR_registry name, char *data);
+static int nr_reg_local_get_uchar(NR_registry name, UCHAR *data);
+static int nr_reg_local_get_int2(NR_registry name, INT2 *data);
+static int nr_reg_local_get_uint2(NR_registry name, UINT2 *data);
+static int nr_reg_local_get_int4(NR_registry name, INT4 *data);
+static int nr_reg_local_get_uint4(NR_registry name, UINT4 *data);
+static int nr_reg_local_get_int8(NR_registry name, INT8 *data);
+static int nr_reg_local_get_uint8(NR_registry name, UINT8 *data);
+static int nr_reg_local_get_double(NR_registry name, double *data);
+static int nr_reg_local_get_registry(NR_registry name, NR_registry data);
+static int nr_reg_local_get_bytes(NR_registry name, UCHAR *data, size_t size, size_t *length);
+static int nr_reg_local_get_string(NR_registry name, char *data, size_t size);
+static int nr_reg_local_get_length(NR_registry name, size_t *len);
+static int nr_reg_local_get_type(NR_registry name, NR_registry_type type);
+static int nr_reg_local_set_char(NR_registry name, char data);
+static int nr_reg_local_set_uchar(NR_registry name, UCHAR data);
+static int nr_reg_local_set_int2(NR_registry name, INT2 data);
+static int nr_reg_local_set_uint2(NR_registry name, UINT2 data);
+static int nr_reg_local_set_int4(NR_registry name, INT4 data);
+static int nr_reg_local_set_uint4(NR_registry name, UINT4 data);
+static int nr_reg_local_set_int8(NR_registry name, INT8 data);
+static int nr_reg_local_set_uint8(NR_registry name, UINT8 data);
+static int nr_reg_local_set_double(NR_registry name, double data);
+static int nr_reg_local_set_registry(NR_registry name);
+static int nr_reg_local_set_bytes(NR_registry name, UCHAR *data, size_t length);
+static int nr_reg_local_set_string(NR_registry name, char *data);
+static int nr_reg_local_del(NR_registry name);
+static int nr_reg_local_get_child_count(NR_registry parent, size_t *count);
+static int nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length);
+static int nr_reg_local_fin(NR_registry name);
+static int nr_reg_local_dump(int sorted);
+static int nr_reg_insert_node(char *name, void *node);
+static int nr_reg_change_node(char *name, void *node, void *old);
+static int nr_reg_get(char *name, int type, void *out);
+static int nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out);
+static int nr_reg_get_array(char *name, unsigned char type, UCHAR *out, size_t size, size_t *length);
+static int nr_reg_set(char *name, int type, void *data);
+static int nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length);
+static int nr_reg_set_parent_registries(char *name);
+
+/* make these static OLD_REGISTRY */
+#if 0
+static int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
+static char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
+#else
+int nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node);
+char *nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit);
+#endif
+static int nr_reg_rfree(void *ptr);
+#if 0 /* Unused currently */
+static int nr_reg_noop(void *ptr);
+#endif
+static int nr_reg_compute_length(char *name, nr_registry_node *node, size_t *length);
+char *nr_reg_action_name(int action);
+
+/* the registry, containing mappings like "foo.bar.baz" to registry
+ * nodes, which are either of type nr_scalar_registry_node or
+ * nr_array_registry_node */
+static r_assoc *nr_registry = 0;
+
+#if 0 /* Unused currently */
+static nr_array_registry_node nr_top_level_node;
+#endif
+
+typedef struct nr_reg_find_children_arg_ {
+ size_t size;
+ NR_registry *children;
+ size_t length;
+} nr_reg_find_children_arg;
+
+static int nr_reg_local_iter(char *prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr);
+static int nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
+static int nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
+static int nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
+static int nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node);
+
+
+
+int
+nr_reg_local_iter(NR_registry prefix, int (*action)(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node), void *ptr)
+{
+ int r, _status;
+ r_assoc_iterator iter;
+ char *name;
+ int namel;
+ nr_registry_node *node;
+ int prefixl;
+
+ if (prefix == 0)
+ ABORT(R_INTERNAL);
+
+ if ((r=r_assoc_init_iter(nr_registry, &iter)))
+ ABORT(r);
+
+ prefixl = strlen(prefix);
+
+ for (;;) {
+ if ((r=r_assoc_iter(&iter, (void*)&name, &namel, (void*)&node))) {
+ if (r == R_EOD)
+ break;
+ else
+ ABORT(r);
+ }
+
+ /* subtract to remove the '\0' character from the string length */
+ --namel;
+
+ /* sanity check that the name is null-terminated */
+ assert(namel >= 0);
+ assert(name[namel] == '\0');
+
+ if (namel < 0 || name[namel] != '\0' || node == 0)
+ break;
+
+ /* 3 cases where action will be called:
+ * 1) prefix == ""
+ * 2) prefix == name
+ * 3) name == prefix + '.'
+ */
+ if (prefixl == 0
+ || ((namel == prefixl || (namel > prefixl && name[prefixl] == '.'))
+ && !strncmp(prefix, name, prefixl))) {
+ if ((r=action(ptr, &iter, prefix, name, node)))
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+
+ return(_status);
+}
+
+int
+nr_reg_local_iter_delete(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
+{
+ int r, _status;
+
+ if ((r=r_assoc_iter_delete(iter)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_local_find_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
+{
+ int _status;
+ int prefixl = strlen(prefix);
+ char *dot;
+ nr_reg_find_children_arg *arg = (void*)ptr;
+
+ assert(sizeof(*(arg->children)) == sizeof(NR_registry));
+
+ /* only grovel through immediate children */
+ if (prefixl == 0 || name[prefixl] == '.') {
+ if (name[prefixl] != '\0') {
+ dot = strchr(&name[prefixl+1], '.');
+ if (dot == 0) {
+ strncpy(arg->children[arg->length], name, sizeof(NR_registry)-1);
+ ++arg->length;
+
+ /* only grab as many as there are room for */
+ if (arg->length >= arg->size)
+ ABORT(R_INTERRUPTED);
+ }
+ }
+ }
+
+ _status = 0;
+ abort:
+ return _status;
+}
+
+int
+nr_reg_local_count_children(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
+{
+ int prefixl = strlen(prefix);
+ char *dot;
+
+ /* only count children */
+ if (name[prefixl] == '.') {
+ dot = strchr(&name[prefixl+1], '.');
+ if (dot == 0)
+ ++(*(unsigned int *)ptr);
+ }
+ else if (name[0] != '\0') {
+ if (prefixl == 0)
+ ++(*(unsigned int *)ptr);
+ }
+
+ return 0;
+}
+
+int
+nr_reg_local_dump_print(void *ptr, r_assoc_iterator *iter, char *prefix, char *name, nr_registry_node *node)
+{
+ int _status;
+ int freeit = 0;
+ char *data;
+
+ /* only print leaf nodes */
+ if (node->type != NR_REG_TYPE_REGISTRY) {
+ data = nr_reg_alloc_node_data(name, node, &freeit);
+ if (ptr)
+ fprintf((FILE*)ptr, "%s: %s\n", name, data);
+ else
+ r_log(NR_LOG_REGISTRY, LOG_INFO, "%s: %s", name, data);
+ if (freeit)
+ RFREE(data);
+ }
+
+ _status=0;
+ //abort:
+ return(_status);
+}
+
+
+#if 0 /* Unused currently */
+int
+nr_reg_noop(void *ptr)
+{
+ return 0;
+}
+#endif
+
+int
+nr_reg_rfree(void *ptr)
+{
+ RFREE(ptr);
+ return 0;
+}
+
+int
+nr_reg_fetch_node(char *name, unsigned char type, nr_registry_node **node, int *free_node)
+{
+ int r, _status;
+
+ *node = 0;
+ *free_node = 0;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)node)))
+ ABORT(r);
+
+ if ((*node)->type != type)
+ ABORT(R_FAILED);
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (*node)
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s'), found '%s' instead",
+ name, nr_reg_type_name(type), nr_reg_type_name((*node)->type));
+ else
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't fetch node '%s' ('%s')",
+ name, nr_reg_type_name(type));
+ }
+ else {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Fetched node '%s' ('%s')",
+ name, nr_reg_type_name(type));
+ }
+ return(_status);
+}
+
+int
+nr_reg_insert_node(char *name, void *node)
+{
+ int r, _status;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ /* since the registry application is not multi-threaded, a node being
+ * inserted should always be a new node because the registry app must
+ * have looked for a node with this key but not found it, so it is
+ * being created/inserted now using R_ASSOC_NEW */
+ if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_NEW)))
+ ABORT(r);
+
+ if ((r=nr_reg_set_parent_registries(name)))
+ ABORT(r);
+
+ if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_ADD)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
+ int freeit;
+ char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
+ r_log(NR_LOG_REGISTRY, LOG_INFO,
+ "insert '%s' (%s) %s: %s", name,
+ nr_reg_type_name(((nr_registry_node*)node)->type),
+ (_status ? "FAILED" : "succeeded"), data);
+ if (freeit)
+ RFREE(data);
+ }
+ return(_status);
+}
+
+int
+nr_reg_change_node(char *name, void *node, void *old)
+{
+ int r, _status;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if (old != node) {
+ if ((r=r_assoc_insert(nr_registry, name, strlen(name)+1, node, 0, nr_reg_rfree, R_ASSOC_REPLACE)))
+ ABORT(r);
+ }
+
+ if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_CHANGE)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (r_logging(NR_LOG_REGISTRY, LOG_INFO)) {
+ int freeit;
+ char *data = nr_reg_alloc_node_data(name, (void*)node, &freeit);
+ r_log(NR_LOG_REGISTRY, LOG_INFO,
+ "change '%s' (%s) %s: %s", name,
+ nr_reg_type_name(((nr_registry_node*)node)->type),
+ (_status ? "FAILED" : "succeeded"), data);
+ if (freeit)
+ RFREE(data);
+ }
+ return(_status);
+}
+
+char *
+nr_reg_alloc_node_data(char *name, nr_registry_node *node, int *freeit)
+{
+ char *s = 0;
+ int len;
+ int alloc = 0;
+ unsigned int i;
+
+ *freeit = 0;
+
+ switch (node->type) {
+ default:
+ alloc = 100; /* plenty of room for any of the scalar types */
+ break;
+ case NR_REG_TYPE_REGISTRY:
+ alloc = strlen(name) + 1;
+ break;
+ case NR_REG_TYPE_BYTES:
+ alloc = (2 * ((nr_array_registry_node*)node)->array.length) + 1;
+ break;
+ case NR_REG_TYPE_STRING:
+ alloc = 0;
+ break;
+ }
+
+ if (alloc > 0) {
+ s = (void*)RMALLOC(alloc);
+ if (!s)
+ return "";
+
+ *freeit = 1;
+ }
+
+ len = alloc;
+
+ switch (node->type) {
+ case NR_REG_TYPE_CHAR:
+ i = ((nr_scalar_registry_node*)node)->scalar._char;
+ if (isprint(i) && ! isspace(i))
+ snprintf(s, len, "%c", (char)i);
+ else
+ snprintf(s, len, "\\%03o", (char)i);
+ break;
+ case NR_REG_TYPE_UCHAR:
+ snprintf(s, len, "0x%02x", ((nr_scalar_registry_node*)node)->scalar._uchar);
+ break;
+ case NR_REG_TYPE_INT2:
+ snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int2);
+ break;
+ case NR_REG_TYPE_UINT2:
+ snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint2);
+ break;
+ case NR_REG_TYPE_INT4:
+ snprintf(s, len, "%d", ((nr_scalar_registry_node*)node)->scalar._nr_int4);
+ break;
+ case NR_REG_TYPE_UINT4:
+ snprintf(s, len, "%u", ((nr_scalar_registry_node*)node)->scalar._nr_uint4);
+ break;
+ case NR_REG_TYPE_INT8:
+ snprintf(s, len, "%lld", ((nr_scalar_registry_node*)node)->scalar._nr_int8);
+ break;
+ case NR_REG_TYPE_UINT8:
+ snprintf(s, len, "%llu", ((nr_scalar_registry_node*)node)->scalar._nr_uint8);
+ break;
+ case NR_REG_TYPE_DOUBLE:
+ snprintf(s, len, "%#f", ((nr_scalar_registry_node*)node)->scalar._double);
+ break;
+ case NR_REG_TYPE_REGISTRY:
+ snprintf(s, len, "%s", name);
+ break;
+ case NR_REG_TYPE_BYTES:
+ for (i = 0; i < ((nr_array_registry_node*)node)->array.length; ++i) {
+ sprintf(&s[2*i], "%02x", ((nr_array_registry_node*)node)->array.data[i]);
+ }
+ break;
+ case NR_REG_TYPE_STRING:
+ s = (char*)((nr_array_registry_node*)node)->array.data;
+ break;
+ default:
+ assert(0); /* bad value */
+ *freeit = 0;
+ s = "";
+ break;
+ }
+
+ return s;
+}
+
+int
+nr_reg_get(char *name, int type, void *out)
+{
+ int r, _status;
+ nr_scalar_registry_node *node = 0;
+ int free_node = 0;
+
+ if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
+ ABORT(r);
+
+ if ((r=nr_reg_get_data(name, node, out)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ if (free_node) RFREE(node);
+ return(_status);
+}
+
+int
+nr_reg_get_data(NR_registry name, nr_scalar_registry_node *node, void *out)
+{
+ int _status;
+
+ switch (node->type) {
+ case NR_REG_TYPE_CHAR:
+ *(char*)out = node->scalar._char;
+ break;
+ case NR_REG_TYPE_UCHAR:
+ *(UCHAR*)out = node->scalar._uchar;
+ break;
+ case NR_REG_TYPE_INT2:
+ *(INT2*)out = node->scalar._nr_int2;
+ break;
+ case NR_REG_TYPE_UINT2:
+ *(UINT2*)out = node->scalar._nr_uint2;
+ break;
+ case NR_REG_TYPE_INT4:
+ *(INT4*)out = node->scalar._nr_int4;
+ break;
+ case NR_REG_TYPE_UINT4:
+ *(UINT4*)out = node->scalar._nr_uint4;
+ break;
+ case NR_REG_TYPE_INT8:
+ *(INT8*)out = node->scalar._nr_int8;
+ break;
+ case NR_REG_TYPE_UINT8:
+ *(UINT8*)out = node->scalar._nr_uint8;
+ break;
+ case NR_REG_TYPE_DOUBLE:
+ *(double*)out = node->scalar._double;
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_get_array(char *name, unsigned char type, unsigned char *out, size_t size, size_t *length)
+{
+ int r, _status;
+ nr_array_registry_node *node = 0;
+ int free_node = 0;
+
+ if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
+ ABORT(r);
+
+ if (size < node->array.length)
+ ABORT(R_BAD_ARGS);
+
+ if (out != 0)
+ memcpy(out, node->array.data, node->array.length);
+ if (length != 0)
+ *length = node->array.length;
+
+ _status=0;
+ abort:
+ if (node && free_node) RFREE(node);
+ return(_status);
+}
+
+int
+nr_reg_set(char *name, int type, void *data)
+{
+ int r, _status;
+ nr_scalar_registry_node *node = 0;
+ int create_node = 0;
+ int changed = 0;
+ int free_node = 0;
+
+ if ((r=nr_reg_fetch_node(name, type, (void*)&node, &free_node)))
+ if (r == R_NOT_FOUND) {
+ create_node = 1;
+ free_node = 1;
+ }
+ else
+ ABORT(r);
+
+ if (create_node) {
+ if (!(node=(void*)RCALLOC(sizeof(nr_scalar_registry_node))))
+ ABORT(R_NO_MEMORY);
+
+ node->type = type;
+ }
+ else {
+ if (node->type != type)
+ ABORT(R_BAD_ARGS);
+ }
+
+ switch (type) {
+#define CASE(TYPE, _name, type) \
+ case TYPE: \
+ if (node->scalar._name != *(type*)data) { \
+ node->scalar._name = *(type*)data; \
+ if (! create_node) \
+ changed = 1; \
+ } \
+ break;
+ CASE(NR_REG_TYPE_CHAR, _char, char)
+ CASE(NR_REG_TYPE_UCHAR, _uchar, UCHAR)
+ CASE(NR_REG_TYPE_INT2, _nr_int2, INT2)
+ CASE(NR_REG_TYPE_UINT2, _nr_uint2, UINT2)
+ CASE(NR_REG_TYPE_INT4, _nr_int4, INT4)
+ CASE(NR_REG_TYPE_UINT4, _nr_uint4, UINT4)
+ CASE(NR_REG_TYPE_INT8, _nr_int8, INT8)
+ CASE(NR_REG_TYPE_UINT8, _nr_uint8, UINT8)
+ CASE(NR_REG_TYPE_DOUBLE, _double, double)
+#undef CASE
+
+ case NR_REG_TYPE_REGISTRY:
+ /* do nothing */
+ break;
+
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ if (create_node) {
+ if ((r=nr_reg_insert_node(name, node)))
+ ABORT(r);
+ free_node = 0;
+ }
+ else {
+ if (changed) {
+ if ((r=nr_reg_change_node(name, node, node)))
+ ABORT(r);
+ free_node = 0;
+ }
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ if (node && free_node) RFREE(node);
+ }
+ return(_status);
+}
+
+int
+nr_reg_set_array(char *name, unsigned char type, UCHAR *data, size_t length)
+{
+ int r, _status;
+ nr_array_registry_node *old = 0;
+ nr_array_registry_node *node = 0;
+ int free_node = 0;
+ int added = 0;
+ int changed = 0;
+
+ if ((r=nr_reg_fetch_node(name, type, (void*)&old, &free_node))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+ else {
+ assert(free_node == 0);
+ }
+
+ if (old) {
+ if (old->type != type)
+ ABORT(R_BAD_ARGS);
+
+ if (old->array.length != length
+ || memcmp(old->array.data, data, length)) {
+ changed = 1;
+
+ if (old->array.length < length) {
+ if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
+ ABORT(R_NO_MEMORY);
+ }
+ else {
+ node = old;
+ }
+ }
+ }
+ else {
+ if (!(node=(void*)RCALLOC(sizeof(nr_array_registry_node)+length)))
+ ABORT(R_NO_MEMORY);
+
+ added = 1;
+ }
+
+ if (added || changed) {
+ node->type = type;
+ node->array.length = length;
+ memcpy(node->array.data, data, length);
+ }
+
+ if (added) {
+ if ((r=nr_reg_insert_node(name, node)))
+ ABORT(r);
+ }
+ else if (changed) {
+ if ((r=nr_reg_change_node(name, node, old)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_set_parent_registries(char *name)
+{
+ int r, _status;
+ char *parent = 0;
+ char *dot;
+
+ if ((parent = r_strdup(name)) == 0)
+ ABORT(R_NO_MEMORY);
+
+ if ((dot = strrchr(parent, '.')) != 0) {
+ *dot = '\0';
+ if ((r=NR_reg_set_registry(parent)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (parent) RFREE(parent);
+ return(_status);
+}
+
+
+
+
+
+/* NON-STATIC METHODS */
+
+int
+nr_reg_is_valid(NR_registry name)
+{
+ int _status;
+ unsigned int length;
+ unsigned int i;
+
+ if (name == 0)
+ ABORT(R_BAD_ARGS);
+
+ /* make sure the key is null-terminated */
+ if (memchr(name, '\0', sizeof(NR_registry)) == 0)
+ ABORT(R_BAD_ARGS);
+
+ length = strlen(name);
+
+ /* cannot begin or end with a period */
+ if (name[0] == '.')
+ ABORT(R_BAD_ARGS);
+ if (strlen(name) > 0 && name[length-1] == '.')
+ ABORT(R_BAD_ARGS);
+
+ /* all characters cannot be space, and must be printable and not / */
+ for (i = 0; i < length; ++i) {
+ if (isspace(name[i]) || ! (isprint(name[i]) || name[i] == '/'))
+ ABORT(R_BAD_ARGS);
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "invalid name '%s'", name);
+ }
+ return(_status);
+}
+
+
+int
+nr_reg_compute_length(char *name, nr_registry_node *in, size_t *length)
+{
+ int _status;
+ nr_array_registry_node *node = (nr_array_registry_node*)in;
+
+ switch (node->type) {
+ case NR_REG_TYPE_STRING:
+ *length = node->array.length - 1;
+ break;
+ case NR_REG_TYPE_BYTES:
+ *length = node->array.length;
+ break;
+ case NR_REG_TYPE_CHAR:
+ *length = sizeof(char);
+ break;
+ case NR_REG_TYPE_UCHAR:
+ *length = sizeof(UCHAR);
+ break;
+ case NR_REG_TYPE_INT2:
+ case NR_REG_TYPE_UINT2:
+ *length = 2;
+ break;
+ case NR_REG_TYPE_INT4:
+ case NR_REG_TYPE_UINT4:
+ *length = 4;
+ break;
+ case NR_REG_TYPE_INT8:
+ case NR_REG_TYPE_UINT8:
+ *length = 8;
+ break;
+ case NR_REG_TYPE_DOUBLE:
+ *length = sizeof(double);
+ break;
+ case NR_REG_TYPE_REGISTRY:
+ *length = strlen(name);
+ break;
+ default:
+ ABORT(R_INTERNAL);
+ break;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+/* VTBL METHODS */
+
+int
+nr_reg_local_init(nr_registry_module *me)
+{
+ int r, _status;
+
+ if (nr_registry == 0) {
+ if ((r=r_assoc_create(&nr_registry, r_assoc_crc32_hash_compute, 12)))
+ ABORT(r);
+
+ if ((r=nr_reg_cb_init()))
+ ABORT(r);
+
+ /* make sure NR_TOP_LEVEL_REGISTRY always exists */
+ if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+#define NRREGGET(func, TYPE, type) \
+int \
+func(NR_registry name, type *out) \
+{ \
+ return nr_reg_get(name, TYPE, out); \
+}
+
+NRREGGET(nr_reg_local_get_char, NR_REG_TYPE_CHAR, char)
+NRREGGET(nr_reg_local_get_uchar, NR_REG_TYPE_UCHAR, UCHAR)
+NRREGGET(nr_reg_local_get_int2, NR_REG_TYPE_INT2, INT2)
+NRREGGET(nr_reg_local_get_uint2, NR_REG_TYPE_UINT2, UINT2)
+NRREGGET(nr_reg_local_get_int4, NR_REG_TYPE_INT4, INT4)
+NRREGGET(nr_reg_local_get_uint4, NR_REG_TYPE_UINT4, UINT4)
+NRREGGET(nr_reg_local_get_int8, NR_REG_TYPE_INT8, INT8)
+NRREGGET(nr_reg_local_get_uint8, NR_REG_TYPE_UINT8, UINT8)
+NRREGGET(nr_reg_local_get_double, NR_REG_TYPE_DOUBLE, double)
+
+int
+nr_reg_local_get_registry(NR_registry name, NR_registry out)
+{
+ int r, _status;
+ nr_scalar_registry_node *node = 0;
+ int free_node = 0;
+
+ if ((r=nr_reg_fetch_node(name, NR_REG_TYPE_REGISTRY, (void*)&node, &free_node)))
+ ABORT(r);
+
+ strncpy(out, name, sizeof(NR_registry));
+
+ _status=0;
+ abort:
+ if (free_node) RFREE(node);
+ return(_status);
+
+}
+
+int
+nr_reg_local_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
+{
+ return nr_reg_get_array(name, NR_REG_TYPE_BYTES, out, size, length);
+}
+
+int
+nr_reg_local_get_string(NR_registry name, char *out, size_t size)
+{
+ return nr_reg_get_array(name, NR_REG_TYPE_STRING, (UCHAR*)out, size, 0);
+}
+
+int
+nr_reg_local_get_length(NR_registry name, size_t *length)
+{
+ int r, _status;
+ nr_registry_node *node = 0;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
+ ABORT(r);
+
+ if ((r=nr_reg_compute_length(name, node, length)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_local_get_type(NR_registry name, NR_registry_type type)
+{
+ int r, _status;
+ nr_registry_node *node = 0;
+ char *str;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry, name, strlen(name)+1, (void*)&node)))
+ ABORT(r);
+
+ str = nr_reg_type_name(node->type);
+ if (! str)
+ ABORT(R_BAD_ARGS);
+
+ strncpy(type, str, sizeof(NR_registry_type));
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+#define NRREGSET(func, TYPE, type) \
+int \
+func(NR_registry name, type data) \
+{ \
+ return nr_reg_set(name, TYPE, &data); \
+}
+
+NRREGSET(nr_reg_local_set_char, NR_REG_TYPE_CHAR, char)
+NRREGSET(nr_reg_local_set_uchar, NR_REG_TYPE_UCHAR, UCHAR)
+NRREGSET(nr_reg_local_set_int2, NR_REG_TYPE_INT2, INT2)
+NRREGSET(nr_reg_local_set_uint2, NR_REG_TYPE_UINT2, UINT2)
+NRREGSET(nr_reg_local_set_int4, NR_REG_TYPE_INT4, INT4)
+NRREGSET(nr_reg_local_set_uint4, NR_REG_TYPE_UINT4, UINT4)
+NRREGSET(nr_reg_local_set_int8, NR_REG_TYPE_INT8, INT8)
+NRREGSET(nr_reg_local_set_uint8, NR_REG_TYPE_UINT8, UINT8)
+NRREGSET(nr_reg_local_set_double, NR_REG_TYPE_DOUBLE, double)
+
+int
+nr_reg_local_set_registry(NR_registry name)
+{
+ return nr_reg_set(name, NR_REG_TYPE_REGISTRY, 0);
+}
+
+int
+nr_reg_local_set_bytes(NR_registry name, unsigned char *data, size_t length)
+{
+ return nr_reg_set_array(name, NR_REG_TYPE_BYTES, data, length);
+}
+
+int
+nr_reg_local_set_string(NR_registry name, char *data)
+{
+ return nr_reg_set_array(name, NR_REG_TYPE_STRING, (UCHAR*)data, strlen(data)+1);
+}
+
+int
+nr_reg_local_del(NR_registry name)
+{
+ int r, _status;
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ /* delete from NR_registry */
+ if ((r=nr_reg_local_iter(name, nr_reg_local_iter_delete, 0)))
+ ABORT(r);
+
+ if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_DELETE)))
+ ABORT(r);
+
+ /* if deleting from the root, re-insert the root */
+ if (! strcasecmp(name, NR_TOP_LEVEL_REGISTRY)) {
+ if ((r=nr_reg_local_set_registry(NR_TOP_LEVEL_REGISTRY)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY,
+ (_status ? LOG_INFO : LOG_INFO),
+ "delete of '%s' %s", name,
+ (_status ? "FAILED" : "succeeded"));
+ return(_status);
+}
+
+int
+nr_reg_local_get_child_count(char *parent, size_t *count)
+{
+ int r, _status;
+ nr_registry_node *ignore1;
+ int ignore2;
+
+
+ if ((r=nr_reg_is_valid(parent)))
+ ABORT(r);
+
+ /* test to see whether it is present */
+ if ((r=nr_reg_fetch_node(parent, NR_REG_TYPE_REGISTRY, &ignore1, &ignore2)))
+ ABORT(r);
+
+ /* sanity check that there isn't any memory to free */
+ assert(ignore2 == 0);
+
+ *count = 0;
+
+ if ((r=nr_reg_local_iter(parent, nr_reg_local_count_children, count)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_local_get_children(NR_registry parent, NR_registry *data, size_t size, size_t *length)
+{
+ int r, _status;
+ nr_reg_find_children_arg arg;
+
+ if ((r=nr_reg_is_valid(parent)))
+ ABORT(r);
+
+ arg.children = data;
+ arg.size = size;
+ arg.length = 0;
+
+ if ((r=nr_reg_local_iter(parent, nr_reg_local_find_children, (void*)&arg))) {
+ if (r == R_INTERRUPTED)
+ ABORT(R_BAD_ARGS);
+ else
+ ABORT(r);
+ }
+
+ assert(sizeof(*arg.children) == sizeof(NR_registry));
+ qsort(arg.children, arg.length, sizeof(*arg.children), (void*)strcasecmp);
+
+ *length = arg.length;
+
+ _status = 0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_local_fin(NR_registry name)
+{
+ int r, _status;
+
+ if ((r=nr_reg_raise_event(name, NR_REG_CB_ACTION_FINAL)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_local_dump(int sorted)
+{
+ int r, _status;
+
+ if ((r=nr_reg_local_iter(NR_TOP_LEVEL_REGISTRY, nr_reg_local_dump_print, 0)))
+ ABORT(r);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+
+static nr_registry_module_vtbl nr_reg_local_vtbl = {
+ nr_reg_local_init,
+ nr_reg_local_get_char,
+ nr_reg_local_get_uchar,
+ nr_reg_local_get_int2,
+ nr_reg_local_get_uint2,
+ nr_reg_local_get_int4,
+ nr_reg_local_get_uint4,
+ nr_reg_local_get_int8,
+ nr_reg_local_get_uint8,
+ nr_reg_local_get_double,
+ nr_reg_local_get_registry,
+ nr_reg_local_get_bytes,
+ nr_reg_local_get_string,
+ nr_reg_local_get_length,
+ nr_reg_local_get_type,
+ nr_reg_local_set_char,
+ nr_reg_local_set_uchar,
+ nr_reg_local_set_int2,
+ nr_reg_local_set_uint2,
+ nr_reg_local_set_int4,
+ nr_reg_local_set_uint4,
+ nr_reg_local_set_int8,
+ nr_reg_local_set_uint8,
+ nr_reg_local_set_double,
+ nr_reg_local_set_registry,
+ nr_reg_local_set_bytes,
+ nr_reg_local_set_string,
+ nr_reg_local_del,
+ nr_reg_local_get_child_count,
+ nr_reg_local_get_children,
+ nr_reg_local_fin,
+ nr_reg_local_dump
+};
+
+static nr_registry_module nr_reg_local_module = { 0, &nr_reg_local_vtbl };
+
+void *NR_REG_MODE_LOCAL = &nr_reg_local_module;
+
+
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry_vtbl.h b/media/mtransport/third_party/nrappkit/src/registry/registry_vtbl.h
new file mode 100644
index 000000000..0f75a03b9
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registry_vtbl.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * registry_vtbl.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry_vtbl.h,v $
+ * $Revision: 1.2 $
+ * $Date: 2006/08/16 19:39:14 $
+ *
+ *
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __REGISTRY_VTBL_H__
+#define __REGISTRY_VTBL_H__
+
+typedef struct nr_registry_module_ nr_registry_module;
+
+typedef struct nr_registry_module_vtbl_ {
+ int (*init)(nr_registry_module*);
+
+ int (*get_char)(NR_registry name, char *out);
+ int (*get_uchar)(NR_registry name, UCHAR *out);
+ int (*get_int2)(NR_registry name, INT2 *out);
+ int (*get_uint2)(NR_registry name, UINT2 *out);
+ int (*get_int4)(NR_registry name, INT4 *out);
+ int (*get_uint4)(NR_registry name, UINT4 *out);
+ int (*get_int8)(NR_registry name, INT8 *out);
+ int (*get_uint8)(NR_registry name, UINT8 *out);
+ int (*get_double)(NR_registry name, double *out);
+ int (*get_registry)(NR_registry name, NR_registry out);
+
+ int (*get_bytes)(NR_registry name, UCHAR *out, size_t size, size_t *length);
+ int (*get_string)(NR_registry name, char *out, size_t size);
+ int (*get_length)(NR_registry name, size_t *length);
+ int (*get_type)(NR_registry name, NR_registry_type type);
+
+ int (*set_char)(NR_registry name, char data);
+ int (*set_uchar)(NR_registry name, UCHAR data);
+ int (*set_int2)(NR_registry name, INT2 data);
+ int (*set_uint2)(NR_registry name, UINT2 data);
+ int (*set_int4)(NR_registry name, INT4 data);
+ int (*set_uint4)(NR_registry name, UINT4 data);
+ int (*set_int8)(NR_registry name, INT8 data);
+ int (*set_uint8)(NR_registry name, UINT8 data);
+ int (*set_double)(NR_registry name, double data);
+ int (*set_registry)(NR_registry name);
+
+ int (*set_bytes)(NR_registry name, UCHAR *data, size_t length);
+ int (*set_string)(NR_registry name, char *data);
+
+ int (*del)(NR_registry name);
+
+ int (*get_child_count)(NR_registry parent, size_t *count);
+ int (*get_children)(NR_registry parent, NR_registry *data, size_t size, size_t *length);
+
+ int (*fin)(NR_registry name);
+
+ int (*dump)(int sorted);
+} nr_registry_module_vtbl;
+
+struct nr_registry_module_ {
+ void *handle;
+ nr_registry_module_vtbl *vtbl;
+};
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/registry/registrycb.c b/media/mtransport/third_party/nrappkit/src/registry/registrycb.c
new file mode 100644
index 000000000..d5aaf915d
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/registry/registrycb.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * registrycb.c
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registrycb.c,v $
+ * $Revision: 1.3 $
+ * $Date: 2007/06/26 22:37:51 $
+ *
+ * Callback-related functions
+ *
+ *
+ * Copyright (C) 2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "registry.h"
+#include "registry_int.h"
+#include "r_assoc.h"
+#include "r_errors.h"
+#include "nr_common.h"
+#include "r_log.h"
+#include "r_macros.h"
+
+static char CB_ACTIONS[] = { NR_REG_CB_ACTION_ADD,
+ NR_REG_CB_ACTION_DELETE,
+ NR_REG_CB_ACTION_CHANGE,
+ NR_REG_CB_ACTION_FINAL };
+
+typedef struct nr_reg_cb_info_ {
+ char action;
+ void (*cb)(void *cb_arg, char action, NR_registry name);
+ void *cb_arg;
+ NR_registry name;
+} nr_reg_cb_info;
+
+/* callbacks that are registered, a mapping from names like "foo.bar.baz"
+ * to an r_assoc which contains possibly several nr_reg_cb_info*'s */
+static r_assoc *nr_registry_callbacks = 0;
+
+//static size_t SIZEOF_CB_ID = (sizeof(void (*)()) + 1);
+#define SIZEOF_CB_ID (sizeof(void (*)()) + 1)
+
+static int nr_reg_validate_action(char action);
+static int nr_reg_assoc_destroy(void *ptr);
+static int compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID]);
+static int nr_reg_info_free(void *ptr);
+static int nr_reg_raise_event_recurse(char *name, char *tmp, int action);
+static int nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg);
+static int nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name));
+
+int
+nr_reg_cb_init()
+{
+ int r, _status;
+
+ if (nr_registry_callbacks == 0) {
+ if ((r=r_assoc_create(&nr_registry_callbacks, r_assoc_crc32_hash_compute, 12)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (_status) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "Couldn't init notifications: %s", nr_strerror(_status));
+ }
+ return(_status);
+}
+
+int
+nr_reg_validate_action(char action)
+{
+ int _status;
+ int i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action == CB_ACTIONS[i])
+ return 0;
+ }
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+nr_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
+{
+ int r, _status;
+ r_assoc *assoc;
+ int create_assoc = 0;
+ nr_reg_cb_info *info;
+ int create_info = 0;
+ unsigned char cb_id[SIZEOF_CB_ID];
+
+ if (name == 0 || cb == 0)
+ ABORT(R_BAD_ARGS);
+
+ if (nr_registry_callbacks == 0)
+ ABORT(R_FAILED);
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
+ if (r == R_NOT_FOUND)
+ create_assoc = 1;
+ else
+ ABORT(r);
+ }
+
+ if (create_assoc) {
+ if ((r=r_assoc_create(&assoc, r_assoc_crc32_hash_compute, 5)))
+ ABORT(r);
+
+ if ((r=r_assoc_insert(nr_registry_callbacks, name, strlen(name)+1, assoc, 0, nr_reg_assoc_destroy, R_ASSOC_NEW)))
+ ABORT(r);
+ }
+
+ if ((r=compute_cb_id(cb, action, cb_id)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(assoc, (char*)cb_id, SIZEOF_CB_ID, (void*)&info))) {
+ if (r == R_NOT_FOUND)
+ create_info = 1;
+ else
+ ABORT(r);
+ }
+
+ if (create_info) {
+ if (!(info=(void*)RCALLOC(sizeof(*info))))
+ ABORT(R_NO_MEMORY);
+ }
+
+ strncpy(info->name, name, sizeof(info->name));
+ info->action = action;
+ info->cb = cb;
+ info->cb_arg = cb_arg;
+
+ if (create_info) {
+ if ((r=r_assoc_insert(assoc, (char*)cb_id, SIZEOF_CB_ID, info, 0, nr_reg_info_free, R_ASSOC_NEW)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "register callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded"));
+
+ if (_status) {
+ if (create_info && info) RFREE(info);
+ if (create_assoc && assoc) nr_reg_assoc_destroy(&assoc);
+ }
+ return(_status);
+}
+
+int
+nr_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
+{
+ int r, _status;
+ r_assoc *assoc;
+ int size;
+ unsigned char cb_id[SIZEOF_CB_ID];
+
+ if (name == 0 || cb == 0)
+ ABORT(R_BAD_ARGS);
+
+ if (nr_registry_callbacks == 0)
+ ABORT(R_FAILED);
+
+ if ((r=nr_reg_is_valid(name)))
+ ABORT(r);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, name, strlen(name)+1, (void*)&assoc))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+ else {
+ if ((r=compute_cb_id(cb, action, cb_id)))
+ ABORT(r);
+
+ if ((r=r_assoc_delete(assoc, (char*)cb_id, SIZEOF_CB_ID))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+ }
+
+ if ((r=r_assoc_num_elements(assoc, &size)))
+ ABORT(r);
+
+ if (size == 0) {
+ if ((r=r_assoc_delete(nr_registry_callbacks, name, strlen(name)+1)))
+ ABORT(r);
+ }
+ }
+
+ _status=0;
+ abort:
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "unregister callback %p on '%s' for '%s' %s", cb, name, nr_reg_action_name(action), (_status ? "FAILED" : "succeeded"));
+
+ return(_status);
+}
+
+int
+compute_cb_id(void *cb, char action, unsigned char cb_id[SIZEOF_CB_ID])
+{
+ /* callbacks are identified by the pointer to the cb function plus
+ * the action being watched */
+ assert(sizeof(cb) == sizeof(void (*)()));
+ assert(sizeof(cb) == (SIZEOF_CB_ID - 1));
+
+ memcpy(cb_id, &(cb), sizeof(cb));
+ cb_id[SIZEOF_CB_ID-1] = action;
+
+ return 0;
+}
+
+char *
+nr_reg_action_name(int action)
+{
+ char *name = "*Unknown*";
+
+ switch (action) {
+ case NR_REG_CB_ACTION_ADD: name = "add"; break;
+ case NR_REG_CB_ACTION_DELETE: name = "delete"; break;
+ case NR_REG_CB_ACTION_CHANGE: name = "change"; break;
+ case NR_REG_CB_ACTION_FINAL: name = "final"; break;
+ }
+
+ return name;
+}
+
+int
+nr_reg_assoc_destroy(void *ptr)
+{
+ return r_assoc_destroy((r_assoc**)&ptr);
+}
+
+int
+nr_reg_info_free(void *ptr)
+{
+ RFREE(ptr);
+ return 0;
+}
+
+/* call with tmp=0 */
+int
+nr_reg_raise_event_recurse(char *name, char *tmp, int action)
+{
+ int r, _status;
+ r_assoc *assoc;
+ nr_reg_cb_info *info;
+ r_assoc_iterator iter;
+ char *key;
+ int keyl;
+ char *c;
+ int free_tmp = 0;
+ int count;
+
+ if (tmp == 0) {
+ if (!(tmp = (char*)r_strdup(name)))
+ ABORT(R_NO_MEMORY);
+ free_tmp = 1;
+ }
+
+ if ((r=r_assoc_fetch(nr_registry_callbacks, tmp, strlen(tmp)+1, (void*)&assoc))) {
+ if (r != R_NOT_FOUND)
+ ABORT(r);
+
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found on '%s'", tmp);
+ }
+ else {
+ if (!r_assoc_num_elements(assoc, &count)) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "%d callback%s found on '%s'",
+ count, ((count == 1) ? "" : "s"), tmp);
+ }
+
+ if ((r=r_assoc_init_iter(assoc, &iter)))
+ ABORT(r);
+
+ for (;;) {
+ if ((r=r_assoc_iter(&iter, (void*)&key, &keyl, (void*)&info))) {
+ if (r == R_EOD)
+ break;
+ else
+ ABORT(r);
+ }
+
+ if (info->action == action) {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG,
+ "Invoking callback %p for '%s'",
+ info->cb,
+ nr_reg_action_name(info->action));
+
+ (void)info->cb(info->cb_arg, action, name);
+ }
+ else {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG,
+ "Skipping callback %p for '%s'",
+ info->cb,
+ nr_reg_action_name(info->action));
+ }
+ }
+ }
+
+ if (strlen(tmp) > 0) {
+ c = strrchr(tmp, '.');
+ if (c != 0)
+ *c = '\0';
+ else
+ tmp[0] = '\0';
+
+ if ((r=nr_reg_raise_event_recurse(name, tmp, action)))
+ ABORT(r);
+ }
+
+ _status=0;
+ abort:
+ if (free_tmp && tmp != 0) RFREE(tmp);
+ return(_status);
+}
+
+
+/* NON-STATIC METHODS */
+
+int
+nr_reg_raise_event(char *name, int action)
+{
+ int r, _status;
+ int count;
+ char *event = nr_reg_action_name(action);
+
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "raising event '%s' on '%s'", event, name);
+
+ if (name == 0)
+ ABORT(R_BAD_ARGS);
+
+ if ((r=nr_reg_validate_action(action)))
+ ABORT(r);
+
+ if ((r=r_assoc_num_elements(nr_registry_callbacks, &count)))
+ ABORT(r);
+
+ if (count > 0) {
+ if ((r=nr_reg_raise_event_recurse(name, 0, action)))
+ ABORT(r);
+ }
+ else {
+ r_log(NR_LOG_REGISTRY, LOG_DEBUG, "No callbacks found");
+ return 0;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+/* PUBLIC METHODS */
+
+int
+NR_reg_register_callback(NR_registry name, char action, void (*cb)(void *cb_arg, char action, NR_registry name), void *cb_arg)
+{
+ int r, _status;
+ int i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action & CB_ACTIONS[i]) {
+ if ((r=nr_reg_register_callback(name, CB_ACTIONS[i], cb, cb_arg)))
+ ABORT(r);
+
+ action &= ~(CB_ACTIONS[i]);
+ }
+ }
+
+ if (action)
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+int
+NR_reg_unregister_callback(char *name, char action, void (*cb)(void *cb_arg, char action, NR_registry name))
+{
+ int r, _status;
+ int i;
+
+ for (i = 0; i < sizeof(CB_ACTIONS); ++i) {
+ if (action & CB_ACTIONS[i]) {
+ if ((r=nr_reg_unregister_callback(name, CB_ACTIONS[i], cb)))
+ ABORT(r);
+
+ action &= ~(CB_ACTIONS[i]);
+ }
+ }
+
+ if (action)
+ ABORT(R_BAD_ARGS);
+
+ _status=0;
+ abort:
+ return(_status);
+}
diff --git a/media/mtransport/third_party/nrappkit/src/share/nr_api.h b/media/mtransport/third_party/nrappkit/src/share/nr_api.h
new file mode 100644
index 000000000..ce6055f0d
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/share/nr_api.h
@@ -0,0 +1,51 @@
+/**
+ nr_pce.h
+
+
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@networkresonance.com Wed Jul 19 13:18:39 2006
+ */
+
+
+#ifndef _nr_pce_h
+#define _nr_pce_h
+
+#include <sys/queue.h>
+#include <csi_platform.h>
+#include <r_common.h>
+#include <r_log.h>
+#include <nrstats.h>
+#include <nr_plugin.h>
+#include <async_wait.h>
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/share/nr_common.h b/media/mtransport/third_party/nrappkit/src/share/nr_common.h
new file mode 100644
index 000000000..ac3ff4400
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/share/nr_common.h
@@ -0,0 +1,108 @@
+/**
+ nr_common.h
+
+
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+
+#ifndef _nr_common_h
+#define _nr_common_h
+
+#include <csi_platform.h>
+
+#ifdef USE_MPATROL
+#define USEDEBUG 1
+#include <mpatrol.h>
+#endif
+
+#ifdef USE_DMALLOC
+#include <dmalloc.h>
+#endif
+
+#include <string.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <errno.h>
+#else
+#include <sys/errno.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <r_log.h>
+
+extern int NR_LOG_REASSD;
+
+#include "registry.h"
+#include "nrstats.h"
+
+typedef struct nr_captured_packet_ {
+ UCHAR cap_interface; /* 1 for primary, 2 for secondary */
+ struct timeval ts; /* The time this packet was captured */
+ UINT4 len; /* The length of the packet */
+ UINT8 packet_number; /* The listener's packet index */
+} nr_captured_packet;
+
+#ifndef NR_ROOT_PATH
+#define NR_ROOT_PATH "/usr/local/ctc/"
+#endif
+
+#define NR_ARCHIVE_DIR NR_ROOT_PATH "archive/"
+#define NR_TEMP_DIR NR_ROOT_PATH "tmp/"
+#define NR_ARCHIVE_STATEFILE NR_ROOT_PATH "archive/state"
+#define NR_CAPTURED_PID_FILENAME NR_ROOT_PATH "captured.pid"
+#define NR_REASSD_PID_FILENAME NR_ROOT_PATH "reassd.pid"
+#define NR_MODE_FILENAME NR_ROOT_PATH "mode.txt"
+
+char *nr_revision_number(void);
+
+
+
+
+/* Memory buckets for CTC memory types */
+#define NR_MEM_TCP 1
+#define NR_MEM_HTTP 2
+#define NR_MEM_DELIVERY 3
+#define NR_MEM_OUT_HM 4
+#define NR_MEM_OUT_SSL 5
+#define NR_MEM_SSL 7
+#define NR_MEM_COMMON 8
+#define NR_MEM_CODEC 9
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/share/nr_reg_keys.h b/media/mtransport/third_party/nrappkit/src/share/nr_reg_keys.h
new file mode 100644
index 000000000..b051f51d4
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/share/nr_reg_keys.h
@@ -0,0 +1,167 @@
+/*
+ *
+ * nr_reg_keys.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/share/nr_reg_keys.h,v $
+ * $Revision: 1.3 $
+ * $Date: 2008/01/29 00:34:00 $
+ *
+ *
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __NR_REG_KEYS_H__
+#define __NR_REG_KEYS_H__
+
+#include <stdio.h>
+
+#define NR_REG_NAME_LENGTH_MIN 1
+#define NR_REG_NAME_LENGTH_MAX 32
+
+#define NR_REG_HOSTNAME "hostname"
+#define NR_REG_ADDRESS "address"
+#define NR_REG_NETMASKSIZE "netmasksize"
+#define NR_REG_ADDRESS_NETMASKSIZE "address/netmasksize" /* use only in clic files */
+#define NR_REG_PORT "port"
+
+#define NR_REG_LOGGING_SYSLOG_ENABLED "logging.syslog.enabled"
+#define NR_REG_LOGGING_SYSLOG_SERVERS "logging.syslog.servers"
+#define NR_REG_LOGGING_SYSLOG_FACILITY "logging.syslog.facility"
+#define NR_REG_LOGGING_SYSLOG_LEVEL "logging.syslog.level"
+
+#define NR_REG_CAPTURED_DAEMONS "captured.daemons"
+
+#define NR_REG_LISTEND_ENABLED "listend.enabled"
+
+#define NR_REG_LISTEND_MAX_INPUT_BUFFER_SIZE "listend.max_input_buffer_size"
+#define NR_REG_LISTEND_MAX_INPUT_BUFFER_SIZE_MIN 1 // 1 byte?
+#define NR_REG_LISTEND_MAX_INPUT_BUFFER_SIZE_MAX (10ULL*1024*1024*1024) // 10 GB
+
+#define NR_REG_LISTEND_INTERFACE "listend.interface"
+#define NR_REG_LISTEND_INTERFACE_PRIMARY "listend.interface.primary"
+#define NR_REG_LISTEND_INTERFACE_SECONDARY "listend.interface.secondary"
+#define NR_REG_LISTEND_LISTEN_ON_BOTH_INTERFACES "listend.interface.listen_on_both_interfaces"
+#define NR_REG_LISTEND_ENABLE_VLAN "listend.enable_vlan"
+
+#define NR_REG_LISTEND_LISTEN_TO "listend.listen_to"
+#define NR_REG_LISTEND_IGNORE "listend.ignore"
+
+#define NR_REG_LISTEND_PORT_MIN 0
+#define NR_REG_LISTEND_PORT_MAX 65535
+
+#define NR_REG_REASSD_MAX_MEMORY_CONSUMPTION "reassd.max_memory_consumption"
+#define NR_REG_REASSD_MAX_MEMORY_CONSUMPTION_MIN (10*1024) // 100 KB
+#define NR_REG_REASSD_MAX_MEMORY_CONSUMPTION_MAX (10ULL*1024*1024*1024) // 10 GB
+
+#define NR_REG_REASSD_DECODER_TCP_IGNORE_CHECKSUMS "reassd.decoder.tcp.ignore_checksums"
+
+#define NR_REG_REASSD_DECODER_TCP_MAX_CONNECTIONS_IN_SYN_STATE "reassd.decoder.tcp.max_connections_in_syn_state"
+#define NR_REG_REASSD_DECODER_TCP_MAX_CONNECTIONS_IN_SYN_STATE_MIN 1
+#define NR_REG_REASSD_DECODER_TCP_MAX_CONNECTIONS_IN_SYN_STATE_MAX 500000
+
+#define NR_REG_REASSD_DECODER_TCP_MAX_SIMULTANEOUS_CONNECTIONS "reassd.decoder.tcp.max_simultaneous_connections"
+#define NR_REG_REASSD_DECODER_TCP_MAX_SIMULTANEOUS_CONNECTIONS_MIN 1
+#define NR_REG_REASSD_DECODER_TCP_MAX_SIMULTANEOUS_CONNECTIONS_MAX 1000000 // 1 million
+
+#define NR_REG_REASSD_DECODER_SSL_MAX_SESSION_CACHE_SIZE "reassd.decoder.ssl.max_session_cache_size"
+#define NR_REG_REASSD_DECODER_SSL_MAX_SESSION_CACHE_SIZE_MIN 0
+#define NR_REG_REASSD_DECODER_SSL_MAX_SESSION_CACHE_SIZE_MAX (1ULL*1024*1024*1024) // 1GB
+
+#define NR_REG_REASSD_DECODER_SSL_REVEAL_LOCAL_KEYS "reassd.decoder.ssl.reveal.local.keys"
+
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_RESPONSE_TIMEOUT "reassd.decoder.http.hanging_response_timeout"
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_RESPONSE_TIMEOUT_MIN 1
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_RESPONSE_TIMEOUT_MAX 1023
+
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_TRANSMISSION_TIMEOUT "reassd.decoder.http.hanging_transmission_timeout"
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_TRANSMISSION_TIMEOUT_MIN 1
+#define NR_REG_REASSD_DECODER_HTTP_HANGING_TRANSMISSION_TIMEOUT_MAX 1023
+
+#define NR_REG_REASSD_DECODER_HTTP_MAX_HTTP_MESSAGE_SIZE "reassd.decoder.http.max_http_message_size"
+#define NR_REG_REASSD_DECODER_HTTP_MAX_HTTP_MESSAGE_SIZE_MIN 0
+#define NR_REG_REASSD_DECODER_HTTP_MAX_HTTP_MESSAGE_SIZE_MAX (10ULL*1024*1024*1024)
+
+/* PCE-only: */
+#define NR_REG_LISTEND_ARCHIIVE "listend.archive"
+#define NR_REG_LISTEND_ARCHIVE_MAX_SIZE "listend.archive.max_size"
+#define NR_REG_LISTEND_ARCHIVE_MAX_SIZE_MIN 0
+#define NR_REG_LISTEND_ARCHIVE_MAX_SIZE_MAX (10ULL*1024*1024*1024*1024) // 10 TB
+
+#define NR_REG_LISTEND_ARCHIVE_RECORDING_ENABLED "listend.archive.recording_enabled"
+
+#define NR_REG_REASSD_DECODER_NET_DELIVER_BATCH_INTERVAL "reassd.decoder.net_deliver.batch_interval"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_BATCH_INTERVAL_MIN 0
+#define NR_REG_REASSD_DECODER_NET_DELIVER_BATCH_INTERVAL_MAX 1023
+
+#define NR_REG_REASSD_DECODER_NET_DELIVER_MAX_QUEUE_DEPTH "reassd.decoder.net_deliver.max_queue_depth"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_MAX_QUEUE_DEPTH_MIN 0
+#define NR_REG_REASSD_DECODER_NET_DELIVER_MAX_QUEUE_DEPTH_MAX (1ULL*1024*1024*1024) // 1 GB
+
+#define NR_REG_REASSD_DECODER_NET_DELIVER_MY_KEY_CERTIFICATE "reassd.decoder.net_deliver.my_key.certificate"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_MY_KEY_PRIVATE_KEY "reassd.decoder.net_deliver.my_key.private_key"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_PEER "reassd.decoder.net_deliver.peer"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_PEER_PORT_MIN 0
+#define NR_REG_REASSD_DECODER_NET_DELIVER_PEER_PORT_MAX 65535
+
+#define NR_REG_REASSD_DECODER_NET_DELIVER_POLLING_INTERVAL "reassd.decoder.net_deliver.polling_interval"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_POLLING_INTERVAL_MIN 1
+#define NR_REG_REASSD_DECODER_NET_DELIVER_POLLING_INTERVAL_MAX 1023
+
+#define NR_REG_REASSD_DECODER_NET_DELIVER_STATELESS "reassd.decoder.net_deliver.stateless"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_WATCHDOG_TIMER "reassd.decoder.net_deliver.watchdog_timer"
+#define NR_REG_REASSD_DECODER_NET_DELIVER_WATCHDOG_TIMER_MIN 0
+#define NR_REG_REASSD_DECODER_NET_DELIVER_WATCHDOG_TIMER_MAX 666
+
+/* ASA-only: */
+#define NR_REG_MIGRATE_ENABLED "migrate.enabled"
+
+#define NR_REG_MIGRATE_INACTIVITY_TIMEOUT "migrate.inactivity_timeout"
+#define NR_REG_MIGRATE_INACTIVITY_TIMEOUT_MIN 0
+#define NR_REG_MIGRATE_INACTIVITY_TIMEOUT_MAX 1023
+
+#define NR_REG_MIGRATE_MIN_LOCAL_SIZE "migrate.min_local_size"
+#define NR_REG_MIGRATE_MIN_OVERLAP_SIZE "migrate.min_overlap_size"
+#define NR_REG_MIGRATE_RETRANSMIT_FREQUENCY "migrate.retransmit_frequency"
+#define NR_REG_MIGRATE_RETRIES "migrate.retries"
+#define NR_MIGRATE_LOCATION_NUMBER_MIN 0
+#define NR_MIGRATE_LOCATION_NUMBER_MAX 255
+
+#define NR_REG_REVELATION_ENABLE "revelation.enabled"
+#define NR_REG_REVELATION_MAX_PER_HOUR "revelation.max_per_hour"
+#define NR_REG_REVELATION_MAX_PER_HOUR_PER_PORTAL "revelation.max_per_hour_per_portal"
+
+/* Appliance-only: */
+#define NR_REG_SNMP_ENABLED "snmp.enabled"
+#define NR_REG_CLOCK_TIMEZONE "clock.timezone"
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/stats/nrstats.h b/media/mtransport/third_party/nrappkit/src/stats/nrstats.h
new file mode 100644
index 000000000..0b6c2bc3c
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/stats/nrstats.h
@@ -0,0 +1,118 @@
+/*
+ *
+ * nrstats.h
+ *
+ * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/stats/nrstats.h,v $
+ * $Revision: 1.4 $
+ * $Date: 2007/06/26 22:37:55 $
+ *
+ * API for keeping and sharing statistics
+ *
+ *
+ * Copyright (C) 2003-2005, Network Resonance, Inc.
+ * Copyright (C) 2006, Network Resonance, Inc.
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Resonance, Inc. nor the name of any
+ * contributors to this software may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+#ifndef __NRSTATS_H__
+#define __NRSTATS_H__
+
+#include <sys/types.h>
+#ifdef WIN32
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+#include <r_types.h>
+
+#ifndef CAPTURE_USER
+#define CAPTURE_USER "pcecap"
+#endif
+
+#define NR_MAX_STATS_TYPES 256 /* max number of stats objects */
+#define NR_MAX_STATS_TYPE_NAME 26
+
+typedef struct NR_stats_type_ {
+ char name[NR_MAX_STATS_TYPE_NAME];
+ int (*reset)(void *stats);
+ int (*print)(void *stats, char *stat_namespace, void (*output)(void *handle, const char *fmt, ...), void *handle);
+ int (*get_lib_name)(char **libname);
+ unsigned int size;
+} NR_stats_type;
+
+typedef struct NR_stats_app_ {
+ time_t last_counter_reset;
+ time_t last_restart;
+ UINT8 total_restarts;
+ char version[64];
+} NR_stats_app;
+
+extern NR_stats_type *NR_stats_type_app;
+
+/* everything measured in bytes */
+typedef struct NR_stats_memory_ {
+ UINT8 current_size;
+ UINT8 max_size;
+ UINT8 in_use;
+ UINT8 in_use_max;
+} NR_stats_memory;
+
+extern NR_stats_type *NR_stats_type_memory;
+
+/* all functions below return 0 on success, else they return an
+ * error code */
+
+/* if errprintf is null, warnings and errors will be sent to /dev/null */
+extern int NR_stats_startup(char *app_name, char *user_name, void (*errprintf)(void *handle, const char *fmt, ...), void *errhandle);
+extern int NR_stats_shutdown(void);
+#define NR_STATS_CREATE (1<<0)
+extern int NR_stats_get(char *module_name, NR_stats_type *type, int flag, void **stats);
+extern int NR_stats_clear(void *stats); /* zeroizes */
+extern int NR_stats_reset(void *stats); /* zeros "speedometers" */
+extern int NR_stats_register(NR_stats_type *type);
+extern int NR_stats_acquire_mutex(void *stats);
+extern int NR_stats_release_mutex(void *stats);
+// TODO: should _get_names take an app_name argument (0==all)????
+extern int NR_stats_get_names(unsigned int *nnames, char ***names);
+extern int NR_stats_get_by_name(char *name, NR_stats_type **type, void **stats);
+extern int NR_stats_get_lib_name(void *stats, char **lib_name);
+extern int NR_stats_rmids(void);
+
+extern char *NR_prefix_to_stats_module(char *prefix);
+
+#define NR_INCREMENT_STAT(stat) do { \
+ stat++; if(stat>stat##_max) stat##_max=stat; \
+ } while (0)
+#define NR_UPDATE_STAT(stat,newval) do { \
+ stat=newval; if(stat>stat##_max) stat##_max=stat; \
+ } while (0)
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/util/byteorder.c b/media/mtransport/third_party/nrappkit/src/util/byteorder.c
new file mode 100644
index 000000000..b62e72b8a
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/byteorder.c
@@ -0,0 +1,76 @@
+/**
+ byteorder.c
+
+
+ Copyright (C) 2007, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@networkresonance.com Wed May 16 16:46:00 PDT 2007
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: byteorder.c,v 1.2 2007/06/26 22:37:55 adamcain Exp $";
+
+#include "nr_common.h"
+#ifndef WIN32
+#include <arpa/inet.h>
+#endif
+#include "r_types.h"
+#include "byteorder.h"
+
+#define IS_BIG_ENDIAN (htonl(0x1) == 0x1)
+
+#define BYTE(n,i) (((UCHAR*)&(n))[(i)])
+#define SWAP(n,x,y) tmp=BYTE((n),(x)), \
+ BYTE((n),(x))=BYTE((n),(y)), \
+ BYTE((n),(y))=tmp
+
+UINT8
+nr_htonll(UINT8 hostlonglong)
+{
+ UINT8 netlonglong = hostlonglong;
+ UCHAR tmp;
+
+ if (!IS_BIG_ENDIAN) {
+ SWAP(netlonglong, 0, 7);
+ SWAP(netlonglong, 1, 6);
+ SWAP(netlonglong, 2, 5);
+ SWAP(netlonglong, 3, 4);
+ }
+
+ return netlonglong;
+}
+
+UINT8
+nr_ntohll(UINT8 netlonglong)
+{
+ return nr_htonll(netlonglong);
+}
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/byteorder.h b/media/mtransport/third_party/nrappkit/src/util/byteorder.h
new file mode 100644
index 000000000..8df0589a6
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/byteorder.h
@@ -0,0 +1,47 @@
+/**
+ byteorder.h
+
+
+ Copyright (C) 2007, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@networkresonance.com Wed May 16 16:46:00 PDT 2007
+ */
+
+
+#ifndef _byteorder_h
+#define _byteorder_h
+
+UINT8 nr_htonll(UINT8 hostlonglong);
+
+UINT8 nr_ntohll(UINT8 netlonglong);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/hex.c b/media/mtransport/third_party/nrappkit/src/util/hex.c
new file mode 100644
index 000000000..6ae6600f3
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/hex.c
@@ -0,0 +1,110 @@
+/**
+ hex.c
+
+
+ Copyright (C) 2001-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@network-resonance.com
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: hex.c,v 1.3 2007/06/26 22:37:56 adamcain Exp $";
+
+#include <sys/types.h>
+#include <string.h>
+#include <ctype.h>
+#include "r_common.h"
+#include "hex.h"
+#include "r_log.h"
+
+static char bin2hex_map[][3] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" };
+
+static int hex2bin_map[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0 /* '0' */, 1 /* '1' */, 2 /* '2' */, 3 /* '3' */, 4 /* '4' */, 5 /* '5' */, 6 /* '6' */, 7 /* '7' */, 8 /* '8' */, 9 /* '9' */, -1, -1, -1, -1, -1, -1, -1, 10 /* 'A' */, 11 /* 'B' */, 12 /* 'C' */, 13 /* 'D' */, 14 /* 'E' */, 15 /* 'F' */, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10 /* 'a' */, 11 /* 'b' */, 12 /* 'c' */, 13 /* 'd' */, 14 /* 'e' */, 15 /* 'f' */, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+
+int
+nr_nbin2hex(UCHAR *bin, int binlen, char hex[], size_t size, int *len)
+{
+ int _status;
+ int i;
+
+ if (size < (2*binlen))
+ ABORT(R_BAD_ARGS);
+
+ for (i = 0; i < binlen; ++i) {
+ *hex++ = bin2hex_map[bin[i]][0];
+ *hex++ = bin2hex_map[bin[i]][1];
+ }
+
+ if (size >= (2*binlen)+1)
+ *hex = '\0';
+
+ *len = (2*binlen);
+
+ _status=0;
+ abort:
+ return(_status);
+}
+
+
+int
+nr_nhex2bin(char *hex, int hexlen, UCHAR bin[], size_t size, int *len)
+{
+ int _status;
+ int binlen;
+ int h1;
+ int h2;
+ int i;
+
+ if (hexlen % 2)
+ ABORT(R_BAD_ARGS);
+
+ binlen = hexlen/2;
+
+ if (size < binlen)
+ ABORT(R_BAD_ARGS);
+
+ for (i = 0; i < binlen; ++i) {
+ h1 = hex2bin_map[(int)*hex++];
+ h2 = hex2bin_map[(int)*hex++];
+
+ if (h1 == -1 || h2 == -1)
+ ABORT(R_BAD_ARGS);
+
+ bin[i] = (h1 << 4) | h2;
+ }
+
+ *len = binlen;
+
+ _status=0;
+ abort:
+ return(_status);
+}
diff --git a/media/mtransport/third_party/nrappkit/src/util/hex.h b/media/mtransport/third_party/nrappkit/src/util/hex.h
new file mode 100644
index 000000000..be63594d1
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/hex.h
@@ -0,0 +1,47 @@
+/**
+ hex.h
+
+
+ Copyright (C) 2001-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ briank@network-resonance.com
+ */
+
+
+#ifndef _hex_h
+#define _hex_h
+
+int nr_nbin2hex(UCHAR *bin, int binlen, char hex[], size_t size, int *len);
+int nr_nhex2bin(char *hex, int hexlen, UCHAR bin[], size_t size, int *len);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/assoc.h b/media/mtransport/third_party/nrappkit/src/util/libekr/assoc.h
new file mode 100644
index 000000000..013e78868
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/assoc.h
@@ -0,0 +1,90 @@
+/**
+ assoc.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ assoc.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: assoc.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Sun Jan 17 17:56:35 1999
+ */
+
+
+#ifndef _assoc_h
+#define _assoc_h
+
+typedef struct assoc_ assoc;
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/debug.c b/media/mtransport/third_party/nrappkit/src/util/libekr/debug.c
new file mode 100644
index 000000000..6f913ac67
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/debug.c
@@ -0,0 +1,131 @@
+/**
+ debug.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ debug.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: debug.c,v 1.3 2007/06/26 22:37:57 adamcain Exp $
+
+
+ ekr@rtfm.com Wed Jan 6 17:08:58 1999
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: debug.c,v 1.3 2007/06/26 22:37:57 adamcain Exp $";
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "r_common.h"
+#include "debug.h"
+
+int nr_debug(int class,char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+#ifdef WIN32
+ vprintf(format,ap);
+ printf("\n");
+#else
+ vfprintf(stderr,format,ap);
+ fprintf(stderr,"\n");
+#endif
+ return(0);
+ }
+
+int nr_xdump(name,data,len)
+ char *name;
+ UCHAR *data;
+ int len;
+ {
+ int i;
+
+ if(name){
+ printf("%s[%d]=\n",name,len);
+ }
+ for(i=0;i<len;i++){
+
+ if((len>8) && i && !(i%12)){
+ printf("\n");
+ }
+ printf("%.2x ",data[i]&255);
+ }
+ if(i%12)
+ printf("\n");
+ return(0);
+ }
+
+
+
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/debug.h b/media/mtransport/third_party/nrappkit/src/util/libekr/debug.h
new file mode 100644
index 000000000..34f7b2fb5
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/debug.h
@@ -0,0 +1,94 @@
+/**
+ debug.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ debug.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: debug.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Wed Jan 6 17:13:00 1999
+ */
+
+
+#ifndef _debug_h
+#define _debug_h
+
+// Remove debugging mess from ssldump
+// #define DBG(a)
+
+int nr_debug(int class,char *format,...);
+int nr_xdump(char *name,UCHAR *data, int len);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.c
new file mode 100644
index 000000000..c83d8369f
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.c
@@ -0,0 +1,541 @@
+/**
+ r_assoc.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_assoc.c
+
+ This is an associative array implementation, using an open-chained
+ hash bucket technique.
+
+ Note that this implementation permits each data entry to have
+ separate copy constructors and destructors. This currently wastes
+ space, but could be implemented while saving space by using
+ the high order bit of the length value or somesuch.
+
+ The major problem with this code is it's not resizable, though it
+ could be made so.
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_assoc.c,v 1.4 2007/06/08 17:41:49 adamcain Exp $
+
+ ekr@rtfm.com Sun Jan 17 17:57:15 1999
+ */
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_assoc.c,v 1.4 2007/06/08 17:41:49 adamcain Exp $";
+
+#include <r_common.h>
+#include <string.h>
+#include "r_assoc.h"
+
+typedef struct r_assoc_el_ {
+ char *key;
+ int key_len;
+ void *data;
+ struct r_assoc_el_ *prev;
+ struct r_assoc_el_ *next;
+ int (*copy)(void **n,void *old);
+ int (*destroy)(void *ptr);
+} r_assoc_el;
+
+struct r_assoc_ {
+ int size;
+ int bits;
+ int (*hash_func)(char *key,int len,int size);
+ r_assoc_el **chains;
+ UINT4 num_elements;
+};
+
+#define DEFAULT_TABLE_BITS 5
+
+static int destroy_assoc_chain(r_assoc_el *chain);
+static int r_assoc_fetch_bucket(r_assoc *assoc,
+ char *key,int len,r_assoc_el **bucketp);
+static int copy_assoc_chain(r_assoc_el **knewp, r_assoc_el *old);
+
+int r_assoc_create(assocp,hash_func,bits)
+ r_assoc **assocp;
+ int (*hash_func)(char *key,int len,int size);
+ int bits;
+ {
+ r_assoc *assoc=0;
+ int _status;
+
+ if(!(assoc=(r_assoc *)RCALLOC(sizeof(r_assoc))))
+ ABORT(R_NO_MEMORY);
+ assoc->size=(1<<bits);
+ assoc->bits=bits;
+ assoc->hash_func=hash_func;
+
+ if(!(assoc->chains=(r_assoc_el **)RCALLOC(sizeof(r_assoc_el *)*
+ assoc->size)))
+ ABORT(R_NO_MEMORY);
+
+ *assocp=assoc;
+
+ _status=0;
+ abort:
+ if(_status){
+ r_assoc_destroy(&assoc);
+ }
+ return(_status);
+ }
+
+int r_assoc_destroy(assocp)
+ r_assoc **assocp;
+ {
+ r_assoc *assoc;
+ int i;
+
+ if(!assocp || !*assocp)
+ return(0);
+
+ assoc=*assocp;
+ for(i=0;i<assoc->size;i++)
+ destroy_assoc_chain(assoc->chains[i]);
+
+ RFREE(assoc->chains);
+ RFREE(*assocp);
+
+ return(0);
+ }
+
+static int destroy_assoc_chain(chain)
+ r_assoc_el *chain;
+ {
+ r_assoc_el *nxt;
+
+ while(chain){
+ nxt=chain->next;
+
+ if(chain->destroy)
+ chain->destroy(chain->data);
+
+ RFREE(chain->key);
+
+ RFREE(chain);
+ chain=nxt;
+ }
+
+ return(0);
+ }
+
+static int copy_assoc_chain(knewp,old)
+ r_assoc_el **knewp;
+ r_assoc_el *old;
+ {
+ r_assoc_el *knew=0,*ptr,*tmp;
+ int r,_status;
+
+ ptr=0; /* Pacify GCC's uninitialized warning.
+ It's not correct */
+ if(!old) {
+ *knewp=0;
+ return(0);
+ }
+ for(;old;old=old->next){
+ if(!(tmp=(r_assoc_el *)RCALLOC(sizeof(r_assoc_el))))
+ ABORT(R_NO_MEMORY);
+
+ if(!knew){
+ knew=tmp;
+ ptr=knew;
+ }
+ else{
+ ptr->next=tmp;
+ tmp->prev=ptr;
+ ptr=tmp;
+ }
+
+ ptr->destroy=old->destroy;
+ ptr->copy=old->copy;
+
+ if(old->copy){
+ if(r=old->copy(&ptr->data,old->data))
+ ABORT(r);
+ }
+ else
+ ptr->data=old->data;
+
+ if(!(ptr->key=(char *)RMALLOC(old->key_len)))
+ ABORT(R_NO_MEMORY);
+ memcpy(ptr->key,old->key,ptr->key_len=old->key_len);
+ }
+
+ *knewp=knew;
+
+ _status=0;
+ abort:
+ if(_status){
+ destroy_assoc_chain(knew);
+ }
+ return(_status);
+ }
+
+static int r_assoc_fetch_bucket(assoc,key,len,bucketp)
+ r_assoc *assoc;
+ char *key;
+ int len;
+ r_assoc_el **bucketp;
+ {
+ UINT4 hash_value;
+ r_assoc_el *bucket;
+
+ hash_value=assoc->hash_func(key,len,assoc->bits);
+
+ for(bucket=assoc->chains[hash_value];bucket;bucket=bucket->next){
+ if(bucket->key_len == len && !memcmp(bucket->key,key,len)){
+ *bucketp=bucket;
+ return(0);
+ }
+ }
+
+ return(R_NOT_FOUND);
+ }
+
+int r_assoc_fetch(assoc,key,len,datap)
+ r_assoc *assoc;
+ char *key;
+ int len;
+ void **datap;
+ {
+ r_assoc_el *bucket;
+ int r;
+
+ if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
+ if(r!=R_NOT_FOUND)
+ ERETURN(r);
+ return(r);
+ }
+
+ *datap=bucket->data;
+ return(0);
+ }
+
+int r_assoc_insert(assoc,key,len,data,copy,destroy,how)
+ r_assoc *assoc;
+ char *key;
+ int len;
+ void *data;
+ int (*copy)(void **knew,void *old);
+ int (*destroy)(void *ptr);
+ int how;
+ {
+ r_assoc_el *bucket,*new_bucket=0;
+ int r,_status;
+
+ if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
+ /*Note that we compute the hash value twice*/
+ UINT4 hash_value;
+
+ if(r!=R_NOT_FOUND)
+ ABORT(r);
+ hash_value=assoc->hash_func(key,len,assoc->bits);
+
+ if(!(new_bucket=(r_assoc_el *)RCALLOC(sizeof(r_assoc_el))))
+ ABORT(R_NO_MEMORY);
+ if(!(new_bucket->key=(char *)RMALLOC(len)))
+ ABORT(R_NO_MEMORY);
+ memcpy(new_bucket->key,key,len);
+ new_bucket->key_len=len;
+
+ /*Insert at the list head. Is FIFO a good algorithm?*/
+ if(assoc->chains[hash_value])
+ assoc->chains[hash_value]->prev=new_bucket;
+ new_bucket->next=assoc->chains[hash_value];
+ assoc->chains[hash_value]=new_bucket;
+ bucket=new_bucket;
+ }
+ else{
+ if(!(how&R_ASSOC_REPLACE))
+ ABORT(R_ALREADY);
+
+ if(bucket->destroy)
+ bucket->destroy(bucket->data);
+ }
+
+ bucket->data=data;
+ bucket->copy=copy;
+ bucket->destroy=destroy;
+ assoc->num_elements++;
+
+ _status=0;
+ abort:
+ if(_status && new_bucket){
+ RFREE(new_bucket->key);
+ RFREE(new_bucket);
+ }
+ return(_status);
+ }
+
+int r_assoc_delete(assoc,key,len)
+ r_assoc *assoc;
+ char *key;
+ int len;
+ {
+ int r;
+ r_assoc_el *bucket;
+ UINT4 hash_value;
+
+ if(r=r_assoc_fetch_bucket(assoc,key,len,&bucket)){
+ if(r!=R_NOT_FOUND)
+ ERETURN(r);
+ return(r);
+ }
+
+ /* Now remove the element from the hash chain */
+ if(bucket->prev){
+ bucket->prev->next=bucket->next;
+ }
+ else {
+ hash_value=assoc->hash_func(key,len,assoc->bits);
+ assoc->chains[hash_value]=bucket->next;
+ }
+
+ if(bucket->next)
+ bucket->next->prev=bucket->prev;
+
+ /* Remove the data */
+ if(bucket->destroy)
+ bucket->destroy(bucket->data);
+
+ RFREE(bucket->key);
+ RFREE(bucket);
+ assoc->num_elements--;
+
+ return(0);
+ }
+
+int r_assoc_copy(knewp,old)
+ r_assoc **knewp;
+ r_assoc *old;
+ {
+ int r,_status,i;
+ r_assoc *knew;
+
+ if(!(knew=(r_assoc *)RCALLOC(sizeof(r_assoc))))
+ ABORT(R_NO_MEMORY);
+ knew->size=old->size;
+ knew->bits=old->bits;
+ knew->hash_func=old->hash_func;
+
+ if(!(knew->chains=(r_assoc_el **)RCALLOC(sizeof(r_assoc_el)*old->size)))
+ ABORT(R_NO_MEMORY);
+ for(i=0;i<knew->size;i++){
+ if(r=copy_assoc_chain(knew->chains+i,old->chains[i]))
+ ABORT(r);
+ }
+ knew->num_elements=old->num_elements;
+
+ *knewp=knew;
+
+ _status=0;
+ abort:
+ if(_status){
+ r_assoc_destroy(&knew);
+ }
+ return(_status);
+ }
+
+int r_assoc_num_elements(r_assoc *assoc,int *sizep)
+ {
+ *sizep=assoc->num_elements;
+
+ return(0);
+ }
+
+int r_assoc_init_iter(assoc,iter)
+ r_assoc *assoc;
+ r_assoc_iterator *iter;
+ {
+ int i;
+
+ iter->assoc=assoc;
+ iter->prev_chain=-1;
+ iter->prev=0;
+
+ iter->next_chain=assoc->size;
+ iter->next=0;
+
+ for(i=0;i<assoc->size;i++){
+ if(assoc->chains[i]!=0){
+ iter->next_chain=i;
+ iter->next=assoc->chains[i];
+ break;
+ }
+ }
+
+ return(0);
+ }
+
+int r_assoc_iter(iter,key,keyl,val)
+ r_assoc_iterator *iter;
+ void **key;
+ int *keyl;
+ void **val;
+ {
+ int i;
+ r_assoc_el *ret;
+
+ if(!iter->next)
+ return(R_EOD);
+ ret=iter->next;
+
+ *key=ret->key;
+ *keyl=ret->key_len;
+ *val=ret->data;
+
+ /* Now increment */
+ iter->prev_chain=iter->next_chain;
+ iter->prev=iter->next;
+
+ /* More on this chain */
+ if(iter->next->next){
+ iter->next=iter->next->next;
+ }
+ else{
+ iter->next=0;
+
+ /* FInd the next occupied chain*/
+ for(i=iter->next_chain+1;i<iter->assoc->size;i++){
+ if(iter->assoc->chains[i]){
+ iter->next_chain=i;
+ iter->next=iter->assoc->chains[i];
+ break;
+ }
+ }
+ }
+
+ return(0);
+ }
+
+/* Delete the last returned value*/
+int r_assoc_iter_delete(iter)
+ r_assoc_iterator *iter;
+ {
+ /* First unhook it from the list*/
+ if(!iter->prev->prev){
+ /* First element*/
+ iter->assoc->chains[iter->prev_chain]=iter->prev->next;
+ }
+ else{
+ iter->prev->prev->next=iter->prev->next;
+ }
+
+ if(iter->prev->next){
+ iter->prev->next->prev=iter->prev->prev;
+ }
+
+ if (iter->prev->destroy)
+ iter->prev->destroy(iter->prev->data);
+
+ iter->assoc->num_elements--;
+ RFREE(iter->prev->key);
+ RFREE(iter->prev);
+ return(0);
+ }
+
+
+/*This is a hack from AMS. Supposedly, it's pretty good for strings, even
+ though it doesn't take into account all the data*/
+int r_assoc_simple_hash_compute(key,len,bits)
+ char *key;
+ int len;
+ int bits;
+ {
+ UINT4 h=0;
+
+ h=key[0] +(key[len-1] * len);
+
+ h &= (1<<bits) - 1;
+
+ return(h);
+ }
+
+
+int r_crc32(char *data,int len,UINT4 *crcval);
+
+int r_assoc_crc32_hash_compute(data,len,bits)
+ char *data;
+ int len;
+ int bits;
+ {
+ UINT4 res;
+ UINT4 mask;
+
+ /* First compute the CRC value */
+ if(r_crc32(data,len,&res))
+ ERETURN(R_INTERNAL);
+
+ mask=~(0xffffffff<<bits);
+
+ return(res & mask);
+ }
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.h
new file mode 100644
index 000000000..5311542c9
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_assoc.h
@@ -0,0 +1,126 @@
+/**
+ r_assoc.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_assoc.h
+
+ Associative array code. This code has the advantage that different
+ elements can have different create and destroy operators. Unfortunately,
+ this can waste space.
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_assoc.h,v 1.3 2007/06/08 22:16:08 adamcain Exp $
+
+
+ ekr@rtfm.com Sun Jan 17 17:57:18 1999
+ */
+
+
+#ifndef _r_assoc_h
+#define _r_assoc_h
+
+typedef struct r_assoc_ r_assoc;
+
+int r_assoc_create(r_assoc **assocp,
+ int (*hash_func)(char *,int,int),
+ int bits);
+int r_assoc_insert(r_assoc *assoc,char *key,int len,
+ void *value,int (*copy)(void **knew,void *old),
+ int (*destroy)(void *ptr),int how);
+#define R_ASSOC_REPLACE 0x1
+#define R_ASSOC_NEW 0x2
+
+int r_assoc_fetch(r_assoc *assoc,char *key, int len, void **value);
+int r_assoc_delete(r_assoc *assoc,char *key, int len);
+
+int r_assoc_copy(r_assoc **knew,r_assoc *old);
+int r_assoc_destroy(r_assoc **assocp);
+int r_assoc_simple_hash_compute(char *key, int len,int bits);
+int r_assoc_crc32_hash_compute(char *key, int len,int bits);
+
+/*We need iterators, but I haven't written them yet*/
+typedef struct r_assoc_iterator_ {
+ r_assoc *assoc;
+ int prev_chain;
+ struct r_assoc_el_ *prev;
+ int next_chain;
+ struct r_assoc_el_ *next;
+} r_assoc_iterator;
+
+int r_assoc_init_iter(r_assoc *assoc,r_assoc_iterator *);
+int r_assoc_iter(r_assoc_iterator *iter,void **key,int *keyl, void **val);
+int r_assoc_iter_delete(r_assoc_iterator *);
+
+int r_assoc_num_elements(r_assoc *assoc,int *sizep);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_common.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_common.h
new file mode 100644
index 000000000..c11bb3d0f
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_common.h
@@ -0,0 +1,100 @@
+/**
+ r_common.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_common.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_common.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Dec 22 10:40:07 1998
+ */
+
+
+#ifndef _r_common_h
+#define _r_common_h
+
+#include "r_defaults.h"
+#include "r_includes.h"
+#include "r_types.h"
+#include "r_macros.h"
+#include "r_errors.h"
+#include "r_data.h"
+
+/* defines for possibly replaced functions */
+#ifndef HAVE_STRDUP
+char *strdup(char *in);
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c
new file mode 100644
index 000000000..f1aca53ec
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c
@@ -0,0 +1,177 @@
+/**
+ r_crc32.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ crc32.c
+
+ Copyright (C) 2003, RTFM, Inc.
+ All Rights Reserved.
+
+ ekr@rtfm.com Fri Jan 31 13:57:43 2003
+
+ THE FOLLOWING CODE WAS EXTRACTED FROM FreeBSD
+ The comment below was the original header
+
+ The main function was modified to process a buffer
+ rather than a file
+ */
+
+/*
+ * This code implements the AUTODIN II polynomial used by Ethernet,
+ * and can be used to calculate multicast address hash indices.
+ * It assumes that the low order bits will be transmitted first,
+ * and consequently the low byte should be sent first when
+ * the crc computation is finished. The crc should be complemented
+ * before transmission.
+ * The variable corresponding to the macro argument "crc" should
+ * be an unsigned long and should be preset to all ones for Ethernet
+ * use. An error-free packet will leave 0xDEBB20E3 in the crc.
+ * Spencer Garrett <srg@quick.com>
+ */
+
+
+#include <sys/types.h>
+#include <r_types.h>
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_crc32.c,v 1.4 2008/11/26 03:22:02 adamcain Exp $";
+
+#ifdef WIN32
+#define u_int32_t UINT4
+#endif
+
+#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ * x^32 + x^26 + x^23 + x^22 + x^16 +
+ * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const u_int32_t crctab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+#include <stdio.h>
+#include <sys/types.h>
+
+
+int r_crc32 (char *buf,int dlen,u_int32_t *cval);
+
+int
+r_crc32(buf, dlen, cval)
+ char *buf;
+ int dlen;
+ u_int32_t *cval;
+{
+ u_int32_t crc = ~0;
+ char *p ;
+ int i;
+ u_int32_t crc32_total = 0 ;
+
+ p=buf;
+
+ for(i=0;i<dlen;i++){
+ CRC(crc, *p) ;
+ CRC(crc32_total, *p) ;
+ p++;
+ }
+
+ *cval = ~crc ;
+
+ return 0 ;
+}
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.h
new file mode 100644
index 000000000..c11be4e04
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.h
@@ -0,0 +1,14 @@
+/**
+ r_crc32.h
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ All Rights Reserved.
+
+ */
+
+#ifndef _r_crc32_
+#define _r_crc32_
+
+int r_crc32 (char *buf,int dlen, UINT4 *cval);
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.c
new file mode 100644
index 000000000..add527575
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.c
@@ -0,0 +1,249 @@
+/**
+ r_data.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_data.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_data.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+ ekr@rtfm.com Tue Aug 17 15:39:50 1999
+ */
+
+
+static char *RCSSTRING __UNUSED__ =(char *)"$Id: r_data.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $";
+
+#include <string.h>
+#include <r_common.h>
+#include <r_data.h>
+#include <string.h>
+
+int r_data_create(dp,d,l)
+ Data **dp;
+ const UCHAR *d;
+ int l;
+ {
+ Data *d_=0;
+ int _status;
+
+ if(!(d_=(Data *)RCALLOC(sizeof(Data))))
+ ABORT(R_NO_MEMORY);
+ if(!(d_->data=(UCHAR *)RMALLOC(l)))
+ ABORT(R_NO_MEMORY);
+
+ memcpy(d_->data,d,l);
+ d_->len=l;
+
+ *dp=d_;
+
+ _status=0;
+ abort:
+ if(_status)
+ r_data_destroy(&d_);
+
+ return(_status);
+ }
+
+
+int r_data_alloc_mem(d,l)
+ Data *d;
+ int l;
+ {
+ int _status;
+
+ if(!(d->data=(UCHAR *)RMALLOC(l)))
+ ABORT(R_NO_MEMORY);
+ d->len=l;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int r_data_alloc(dp,l)
+ Data **dp;
+ int l;
+ {
+ Data *d_=0;
+ int _status;
+
+ if(!(d_=(Data *)RCALLOC(sizeof(Data))))
+ ABORT(R_NO_MEMORY);
+ if(!(d_->data=(UCHAR *)RCALLOC(l)))
+ ABORT(R_NO_MEMORY);
+
+ d_->len=l;
+
+ *dp=d_;
+ _status=0;
+ abort:
+ if(_status)
+ r_data_destroy(&d_);
+
+ return(_status);
+ }
+
+int r_data_make(dp,d,l)
+ Data *dp;
+ const UCHAR *d;
+ int l;
+ {
+ if(!(dp->data=(UCHAR *)RMALLOC(l)))
+ ERETURN(R_NO_MEMORY);
+
+ memcpy(dp->data,d,l);
+ dp->len=l;
+
+ return(0);
+ }
+
+int r_data_destroy(dp)
+ Data **dp;
+ {
+ if(!dp || !*dp)
+ return(0);
+
+ if((*dp)->data)
+ RFREE((*dp)->data);
+
+ RFREE(*dp);
+ *dp=0;
+
+ return(0);
+ }
+
+int r_data_destroy_v(v)
+ void *v;
+ {
+ Data *d;
+
+ if(!v)
+ return(0);
+
+ d=(Data *)v;
+ r_data_zfree(d);
+
+ RFREE(d);
+
+ return(0);
+ }
+
+int r_data_destroy_vp(v)
+ void **v;
+ {
+ Data *d;
+
+ if(!v || !*v)
+ return(0);
+
+ d=(Data *)*v;
+ r_data_zfree(d);
+
+ *v=0;
+ RFREE(d);
+
+ return(0);
+ }
+
+int r_data_copy(dst,src)
+ Data *dst;
+ Data *src;
+ {
+ if(!(dst->data=(UCHAR *)RMALLOC(src->len)))
+ ERETURN(R_NO_MEMORY);
+ memcpy(dst->data,src->data,dst->len=src->len);
+ return(0);
+ }
+
+int r_data_zfree(d)
+ Data *d;
+ {
+ if(!d)
+ return(0);
+ if(!d->data)
+ return(0);
+ memset(d->data,0,d->len);
+ RFREE(d->data);
+ return(0);
+ }
+
+int r_data_compare(d1,d2)
+ Data *d1;
+ Data *d2;
+ {
+ if(d1->len<d2->len)
+ return(-1);
+ if(d2->len<d1->len)
+ return(-1);
+ return(memcmp(d1->data,d2->data,d1->len));
+ }
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.h
new file mode 100644
index 000000000..0e46c3196
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_data.h
@@ -0,0 +1,108 @@
+/**
+ r_data.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_data.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_data.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Wed Feb 10 14:18:19 1999
+ */
+
+
+#ifndef _r_data_h
+#define _r_data_h
+
+typedef struct Data_ {
+ UCHAR *data;
+ int len;
+} Data;
+
+int r_data_create(Data **dp,const UCHAR *d,int l);
+int r_data_alloc(Data **dp, int l);
+int r_data_make(Data *dp, const UCHAR *d,int l);
+int r_data_alloc_mem(Data *d,int l);
+int r_data_destroy(Data **dp);
+int r_data_destroy_v(void *v);
+int r_data_destroy_vp(void **vp);
+int r_data_copy(Data *dst,Data *src);
+int r_data_zfree(Data *d);
+int r_data_compare(Data *d1,Data *d2);
+
+#define INIT_DATA(a,b,c) (a).data=b; (a).len=c
+#define ATTACH_DATA(a,b) (a).data=b; (a).len=sizeof(b)
+#define ZERO_DATA(a) (a).data=0; (a).len=0
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_defaults.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_defaults.h
new file mode 100644
index 000000000..0ec91a033
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_defaults.h
@@ -0,0 +1,91 @@
+/**
+ r_defaults.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_defaults.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_defaults.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Dec 22 10:39:14 1998
+ */
+
+
+#ifndef _r_defaults_h
+#define _r_defaults_h
+
+/*The needs defines don't belong here*/
+#define R_NEEDS_STDLIB_H
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.c
new file mode 100644
index 000000000..93203ed02
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.c
@@ -0,0 +1,139 @@
+/**
+ r_errors.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_errors.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_errors.c,v 1.5 2008/11/26 03:22:02 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Feb 16 16:37:05 1999
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_errors.c,v 1.5 2008/11/26 03:22:02 adamcain Exp $";
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "r_common.h"
+#include "r_errors.h"
+
+static struct {
+ int errnum;
+ char *str;
+} errors[] = NR_ERROR_MAPPING;
+
+int nr_verr_exit(char *fmt,...)
+ {
+ va_list ap;
+
+ va_start(ap,fmt);
+ vfprintf(stderr,fmt,ap);
+
+ if (fmt[0] != '\0' && fmt[strlen(fmt)-1] != '\n')
+ fprintf(stderr,"\n");
+
+ exit(1);
+ }
+
+char *
+nr_strerror(int errnum)
+{
+ static char unknown_error[256];
+ int i;
+ char *error = 0;
+
+ for (i = 0; i < sizeof(errors)/sizeof(*errors); ++i) {
+ if (errnum == errors[i].errnum) {
+ error = errors[i].str;
+ break;
+ }
+ }
+
+ if (! error) {
+ snprintf(unknown_error, sizeof(unknown_error), "Unknown error: %d", errnum);
+ error = unknown_error;
+ }
+
+ return error;
+}
+
+int
+nr_strerror_r(int errnum, char *strerrbuf, size_t buflen)
+{
+ char *error = nr_strerror(errnum);
+ snprintf(strerrbuf, buflen, "%s", error);
+ return 0;
+}
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.h
new file mode 100644
index 000000000..f52375b98
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_errors.h
@@ -0,0 +1,127 @@
+/**
+ r_errors.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_errors.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_errors.h,v 1.4 2007/10/12 20:53:24 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Dec 22 10:59:49 1998
+ */
+
+
+#ifndef _r_errors_h
+#define _r_errors_h
+
+#define R_NO_MEMORY 1 /*out of memory*/
+#define R_NOT_FOUND 2 /*Item not found*/
+#define R_INTERNAL 3 /*Unspecified internal error*/
+#define R_ALREADY 4 /*Action already done*/
+#define R_EOD 5 /*end of data*/
+#define R_BAD_ARGS 6 /*Bad arguments*/
+#define R_BAD_DATA 7 /*Bad data*/
+#define R_WOULDBLOCK 8 /*Operation would block */
+#define R_QUEUED 9 /*Operation was queued */
+#define R_FAILED 10 /*Operation failed */
+#define R_REJECTED 11 /* We don't care about this */
+#define R_INTERRUPTED 12 /* Operation interrupted */
+#define R_IO_ERROR 13 /* I/O Error */
+#define R_NOT_PERMITTED 14 /* Permission denied */
+#define R_RETRY 15 /* Retry possible */
+
+#define NR_ERROR_MAPPING {\
+ { R_NO_MEMORY, "Cannot allocate memory" },\
+ { R_NOT_FOUND, "Item not found" },\
+ { R_INTERNAL, "Internal failure" },\
+ { R_ALREADY, "Action already performed" },\
+ { R_EOD, "End of data" },\
+ { R_BAD_ARGS, "Invalid argument" },\
+ { R_BAD_DATA, "Invalid data" },\
+ { R_WOULDBLOCK, "Operation would block" },\
+ { R_QUEUED, "Operation queued" },\
+ { R_FAILED, "Operation failed" },\
+ { R_REJECTED, "Operation rejected" },\
+ { R_INTERRUPTED, "Operation interrupted" },\
+ { R_IO_ERROR, "I/O error" },\
+ { R_NOT_PERMITTED, "Permission Denied" },\
+ { R_RETRY, "Retry may be possible" },\
+ }
+
+int nr_verr_exit(char *fmt,...);
+
+char *nr_strerror(int errnum);
+int nr_strerror_r(int errnum, char *strerrbuf, size_t buflen);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_includes.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_includes.h
new file mode 100644
index 000000000..4fb7af564
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_includes.h
@@ -0,0 +1,98 @@
+/**
+ r_includes.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_includes.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_includes.h,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Dec 22 11:38:50 1998
+ */
+
+
+#ifndef _r_includes_h
+#define _r_includes_h
+
+#ifdef R_NEEDS_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef R_NEEDS_MEMORY_H
+#include <memory.h>
+#endif
+
+#include <stdio.h>
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.c
new file mode 100644
index 000000000..a880f9933
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.c
@@ -0,0 +1,276 @@
+/**
+ r_list.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_list.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_list.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Jan 19 08:36:39 1999
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_list.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $";
+
+#include <r_common.h>
+#include "r_list.h"
+
+typedef struct r_list_el_ {
+ void *data;
+ struct r_list_el_ *next;
+ struct r_list_el_ *prev;
+ int (*copy)(void **new,void *old);
+ int (*destroy)(void **ptr);
+} r_list_el;
+
+struct r_list_ {
+ struct r_list_el_ *first;
+ struct r_list_el_ *last;
+};
+
+int r_list_create(listp)
+ r_list **listp;
+ {
+ r_list *list=0;
+ int _status;
+
+ if(!(list=(r_list *)RCALLOC(sizeof(r_list))))
+ ABORT(R_NO_MEMORY);
+
+ list->first=0;
+ list->last=0;
+ *listp=list;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int r_list_destroy(listp)
+ r_list **listp;
+ {
+ r_list *list;
+ r_list_el *el;
+
+ if(!listp || !*listp)
+ return(0);
+ list=*listp;
+
+ el=list->first;
+
+ while(el){
+ r_list_el *el_t;
+
+ if(el->destroy && el->data)
+ el->destroy(&el->data);
+ el_t=el;
+ el=el->next;
+ RFREE(el_t);
+ }
+
+ RFREE(list);
+ *listp=0;
+
+ return(0);
+ }
+
+int r_list_copy(outp,in)
+ r_list**outp;
+ r_list *in;
+ {
+ r_list *out=0;
+ r_list_el *el,*el2,*last=0;
+ int r, _status;
+
+ if(!in){
+ *outp=0;
+ return(0);
+ }
+
+ if(r=r_list_create(&out))
+ ABORT(r);
+
+ for(el=in->first;el;el=el->next){
+ if(!(el2=(r_list_el *)RCALLOC(sizeof(r_list_el))))
+ ABORT(R_NO_MEMORY);
+
+ if(el->copy && el->data){
+ if(r=el->copy(&el2->data,el->data))
+ ABORT(r);
+ }
+
+ el2->copy=el->copy;
+ el2->destroy=el->destroy;
+
+ if(!(out->first))
+ out->first=el2;
+
+ el2->prev=last;
+ if(last) last->next=el2;
+ last=el2;
+ }
+
+ out->last=last;
+
+ *outp=out;
+
+ _status=0;
+ abort:
+ if(_status)
+ r_list_destroy(&out);
+ return(_status);
+ }
+
+int r_list_insert(list,value,copy,destroy)
+ r_list *list;
+ void *value;
+ int (*copy)(void **out, void *in);
+ int (*destroy)(void **val);
+ {
+ r_list_el *el=0;
+ int _status;
+
+ if(!(el=(r_list_el *)RCALLOC(sizeof(r_list_el))))
+ ABORT(R_NO_MEMORY);
+ el->data=value;
+ el->copy=copy;
+ el->destroy=destroy;
+
+ el->prev=0;
+ el->next=list->first;
+ if(list->first){
+ list->first->prev=el;
+ }
+ list->first=el;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int r_list_append(list,value,copy,destroy)
+ r_list *list;
+ void *value;
+ int (*copy)(void **out, void *in);
+ int (*destroy)(void **val);
+ {
+ r_list_el *el=0;
+ int _status;
+
+ if(!(el=(r_list_el *)RCALLOC(sizeof(r_list_el))))
+ ABORT(R_NO_MEMORY);
+ el->data=value;
+ el->copy=copy;
+ el->destroy=destroy;
+
+ el->prev=list->last;
+ el->next=0;
+
+ if(list->last) list->last->next=el;
+ else list->first=el;
+
+ list->last=el;
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int r_list_init_iter(list,iter)
+ r_list *list;
+ r_list_iterator *iter;
+ {
+ iter->list=list;
+ iter->ptr=list->first;
+
+ return(0);
+ }
+
+int r_list_iter(iter,val)
+ r_list_iterator *iter;
+ void **val;
+ {
+ if(!iter->ptr)
+ return(R_EOD);
+
+ *val=iter->ptr->data;
+ iter->ptr=iter->ptr->next;
+
+ return(0);
+ }
+
+
+
+
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.h
new file mode 100644
index 000000000..bbefc6c39
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_list.h
@@ -0,0 +1,106 @@
+/**
+ r_list.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_list.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_list.h,v 1.3 2007/06/08 17:41:49 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Jan 19 08:36:48 1999
+ */
+
+
+#ifndef _r_list_h
+#define _r_list_h
+
+typedef struct r_list_ r_list;
+
+typedef struct r_list_iterator_ {
+ r_list *list;
+ struct r_list_el_ *ptr;
+} r_list_iterator;
+
+int r_list_create(r_list **listp);
+int r_list_destroy(r_list **listp);
+int r_list_copy(r_list **out,r_list *in);
+int r_list_insert(r_list *list,void *value,
+ int (*copy)(void **knew,void *old),
+ int (*destroy)(void **ptr));
+int r_list_append(r_list *list,void *value,
+ int (*copy)(void **knew,void *old),
+ int (*destroy)(void **ptr));
+int r_list_init_iter(r_list *list,r_list_iterator *iter);
+int r_list_iter(r_list_iterator *iter,void **val);
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h
new file mode 100644
index 000000000..cdae0c180
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h
@@ -0,0 +1,137 @@
+/**
+ r_macros.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_macros.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_macros.h,v 1.3 2007/06/26 22:37:57 adamcain Exp $
+
+ ekr@rtfm.com Tue Dec 22 10:37:32 1998
+ */
+
+
+#ifndef _r_macros_h
+#define _r_macros_h
+
+/* Haven't removed all PROTO_LIST defs yet */
+#define PROTO_LIST(a) a
+
+#ifndef WIN32
+#ifndef __GNUC__
+#define __FUNCTION__ "unknown"
+#endif
+#endif
+
+#ifdef R_TRACE_ERRORS
+#ifdef WIN32
+#define REPORT_ERROR_(caller,a) printf("%s: error %d at %s:%d (function %s)\n", \
+ caller,a,__FILE__,__LINE__,__FUNCTION__)
+#else
+#define REPORT_ERROR_(caller,a) fprintf(stderr,"%s: error %d at %s:%d (function %s)\n", \
+ caller,a,__FILE__,__LINE__,__FUNCTION__)
+#endif
+#else
+#define REPORT_ERROR_(caller,a)
+#endif
+
+#ifndef ERETURN
+#define ERETURN(a) do {int _r=a; if(!_r) _r=-1; REPORT_ERROR_("ERETURN",_r); return(_r);} while(0)
+#endif
+
+#ifndef ABORT
+#define ABORT(a) do { int _r=a; if(!_r) _r=-1; REPORT_ERROR_("ABORT",_r); _status=_r; goto abort;} while(0)
+#endif
+
+#ifndef FREE
+#define FREE(a) if(a) free(a)
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a)>(b))?(b):(a)
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((b)>(a))?(b):(a)
+#endif
+
+#ifdef DEBUG
+#define DBG(a) debug a
+int debug(int cls, char *format,...);
+#else
+#define DBG(a)
+#endif
+
+#define UNIMPLEMENTED do { fprintf(stderr,"%s:%d Function %s unimplemented\n",__FILE__,__LINE__,__FUNCTION__); abort(); } while(0)
+
+#include "r_memory.h"
+
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.c
new file mode 100644
index 000000000..a5c709d41
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.c
@@ -0,0 +1,201 @@
+/**
+ r_memory.c
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Thu Apr 22 20:40:45 2004
+ */
+
+
+static char *RCSSTRING __UNUSED__="$Id: r_memory.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $";
+
+#include <string.h>
+#include <stddef.h>
+#include <assert.h>
+#include "r_common.h"
+#include "r_memory.h"
+
+typedef struct r_malloc_chunk_ {
+#ifdef SANITY_CHECKS
+ UINT4 hdr;
+#endif
+ UCHAR type;
+ UINT4 size;
+ UCHAR memory[1];
+} r_malloc_chunk;
+
+#define CHUNK_MEMORY_OFFSET offsetof(struct r_malloc_chunk_, memory)
+#define GET_CHUNK_ADDR_FROM_MEM_ADDR(memp) \
+ ((struct r_malloc_chunk *)(((unsigned char*)(memp))-CHUNK_MEMORY_OFFSET))
+#define CHUNK_SIZE(size) (size+sizeof(r_malloc_chunk))
+
+#define HDR_FLAG 0x464c4147
+
+static UINT4 mem_usage; /* Includes our header */
+static UINT4 mem_stats[256]; /* Does not include our header */
+
+void *r_malloc(type,size)
+ int type;
+ size_t size;
+ {
+ size_t total;
+ r_malloc_chunk *chunk;
+
+ total=size+sizeof(r_malloc_chunk);
+
+ if(!(chunk=malloc(total)))
+ return(0);
+
+#ifdef SANITY_CHECKS
+ chunk->hdr=HDR_FLAG;
+#endif
+ chunk->type=type;
+ chunk->size=size;
+
+ mem_usage+=CHUNK_SIZE(size);
+ mem_stats[type]+=size;
+
+ return(chunk->memory);
+ }
+
+void *r_calloc(type,number,size)
+ int type;
+ size_t number;
+ size_t size;
+ {
+ void *ret;
+ size_t total;
+
+ total=number*size;
+
+ if(!(ret=r_malloc(type,total)))
+ return(0);
+
+ memset(ret,0,size);
+
+ return(ret);
+ }
+
+void r_free(ptr)
+ void *ptr;
+ {
+ r_malloc_chunk *chunk;
+
+ if(!ptr) return;
+
+ chunk=(r_malloc_chunk *)GET_CHUNK_ADDR_FROM_MEM_ADDR(ptr);
+#ifdef SANITY_CHECKS
+ assert(chunk->hdr==HDR_FLAG);
+#endif
+
+ mem_usage-=CHUNK_SIZE(chunk->size);
+ mem_stats[chunk->type]-=chunk->size;
+
+ free(chunk);
+ }
+
+void *r_realloc(ptr,size)
+ void *ptr;
+ size_t size;
+ {
+ r_malloc_chunk *chunk,*nchunk;
+ size_t total;
+
+ if(!ptr) return(r_malloc(255,size));
+
+ chunk=(r_malloc_chunk *)GET_CHUNK_ADDR_FROM_MEM_ADDR(ptr);
+#ifdef SANITY_CHECKS
+ assert(chunk->hdr==HDR_FLAG);
+#endif
+
+ total=size + sizeof(r_malloc_chunk);
+
+ if(!(nchunk=realloc(chunk,total)))
+ return(0);
+
+ mem_usage-=CHUNK_SIZE(nchunk->size);
+ mem_stats[nchunk->type]-=nchunk->size;
+
+ nchunk->size=size;
+ mem_usage+=CHUNK_SIZE(nchunk->size);
+ mem_stats[nchunk->type]+=nchunk->size;
+
+ return(nchunk->memory);
+ }
+
+char *r_strdup(str)
+ const char *str;
+ {
+ int len;
+ char *nstr;
+
+ if(!str)
+ return(0);
+
+ len=strlen(str)+1;
+
+ if(!(nstr=r_malloc(0,len)))
+ return(0);
+
+ memcpy(nstr,str,len);
+
+ return(nstr);
+ }
+
+int r_mem_get_usage(usagep)
+ UINT4 *usagep;
+ {
+ *usagep=mem_usage;
+
+ return(0);
+ }
+
+int r_memory_dump_stats()
+ {
+ int i;
+
+ printf("Total memory usage: %d\n",mem_usage);
+ printf("Memory usage by bucket\n");
+ for(i=0;i<256;i++){
+ if(mem_stats[i]){
+ printf("%d\t%d\n",i,mem_stats[i]);
+ }
+ }
+ return(0);
+ }
+
+void *r_malloc_compat(size)
+ size_t size;
+ {
+ return(r_malloc(255,size));
+ }
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.h
new file mode 100644
index 000000000..435707076
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_memory.h
@@ -0,0 +1,101 @@
+/**
+ r_memory.h
+
+
+ Copyright (C) 2004, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Sat Apr 24 08:30:00 2004
+ */
+
+
+#ifndef _r_memory_h
+#define _r_memory_h
+
+#define R_MALLOC_X 2
+
+#include "r_types.h"
+
+void *r_malloc(int type, size_t size);
+void *r_malloc_compat(size_t size);
+void *r_calloc(int type,size_t number,size_t size);
+void r_free (void *ptr);
+void *r_realloc(void *ptr,size_t size);
+char *r_strdup(const char *str);
+int r_mem_get_usage(UINT4 *usage);
+int r_memory_dump_stats(void);
+
+#ifdef NO_MALLOC_REPLACE
+
+#ifndef RMALLOC
+#define RMALLOC(a) malloc(a)
+#endif
+
+#ifndef RCALLOC
+#define RCALLOC(a) calloc(1,a)
+#endif
+
+#ifndef RFREE
+#define RFREE(a) if(a) free(a)
+#endif
+
+#ifndef RREALLOC
+#define RREALLOC(a,b) realloc(a,b)
+#endif
+
+#else
+
+
+#ifndef R_MALLOC_TYPE
+#define R_MALLOC_TYPE 0
+#endif
+
+#ifndef RMALLOC
+#define RMALLOC(a) r_malloc(R_MALLOC_TYPE,a)
+#endif
+
+#ifndef RCALLOC
+#define RCALLOC(a) r_calloc(R_MALLOC_TYPE,1,a)
+#endif
+
+#ifndef RFREE
+#define RFREE(a) if(a) r_free(a)
+#endif
+
+#ifndef RREALLOC
+#define RREALLOC(a,b) r_realloc(a,b)
+#endif
+
+#endif
+
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_replace.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_replace.c
new file mode 100644
index 000000000..eb0138775
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_replace.c
@@ -0,0 +1,110 @@
+/**
+ r_replace.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_replace.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_replace.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $
+
+
+ ekr@rtfm.com Sun Oct 1 11:18:49 2000
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_replace.c,v 1.2 2006/08/16 19:39:17 adamcain Exp $";
+
+#include "r_common.h"
+
+#ifndef HAVE_STRDUP
+
+char *strdup(str)
+ char *str;
+ {
+ int len=strlen(str);
+ char *n;
+
+ if(!(n=(char *)malloc(len+1)))
+ return(0);
+
+ memcpy(n,str,len+1);
+
+ return(n);
+ }
+#endif
+
+
+#ifdef SUPPLY_ATEXIT
+int atexit(void (*func)(void)){
+ ;
+}
+#endif
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_thread.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_thread.h
new file mode 100644
index 000000000..212900bcc
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_thread.h
@@ -0,0 +1,68 @@
+/**
+ r_thread.h
+
+
+ Copyright (C) 1999, RTFM, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Tue Feb 23 14:58:36 1999
+ */
+
+
+#ifndef _r_thread_h
+#define _r_thread_h
+
+typedef void *r_thread;
+typedef void *r_rwlock;
+typedef void * r_cond;
+
+int r_thread_fork (void (*func)(void *),void *arg,
+ r_thread *tid);
+int r_thread_destroy (r_thread tid);
+int r_thread_yield (void);
+int r_thread_exit (void);
+int r_thread_wait_last (void);
+int r_thread_self (void);
+
+int r_rwlock_create (r_rwlock **lockp);
+int r_rwlock_destroy (r_rwlock **lock);
+int r_rwlock_lock (r_rwlock *lock,int action);
+
+int r_cond_init (r_cond *cond);
+int r_cond_wait (r_cond cond);
+int r_cond_signal (r_cond cond);
+
+#define R_RWLOCK_UNLOCK 0
+#define R_RWLOCK_RLOCK 1
+#define R_RWLOCK_WLOCK 2
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.c
new file mode 100644
index 000000000..9ba901fc4
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.c
@@ -0,0 +1,238 @@
+/**
+ r_time.c
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_time.c
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_time.c,v 1.5 2008/11/26 03:22:02 adamcain Exp $
+
+ ekr@rtfm.com Thu Mar 4 08:43:46 1999
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: r_time.c,v 1.5 2008/11/26 03:22:02 adamcain Exp $";
+
+#include <r_common.h>
+#include <r_time.h>
+
+/*Note that t1 must be > t0 */
+int r_timeval_diff(t1,t0,diff)
+ struct timeval *t1;
+ struct timeval *t0;
+ struct timeval *diff;
+ {
+ long d;
+
+ if(t0->tv_sec > t1->tv_sec)
+ ERETURN(R_BAD_ARGS);
+ if((t0->tv_sec == t1->tv_sec) && (t0->tv_usec > t1->tv_usec))
+ ERETURN(R_BAD_ARGS);
+
+ /*Easy case*/
+ if(t0->tv_usec <= t1->tv_usec){
+ diff->tv_sec=t1->tv_sec - t0->tv_sec;
+ diff->tv_usec=t1->tv_usec - t0->tv_usec;
+ return(0);
+ }
+
+ /*Hard case*/
+ d=t0->tv_usec - t1->tv_usec;
+ if(t1->tv_sec < (t0->tv_sec + 1))
+ ERETURN(R_BAD_ARGS);
+ diff->tv_sec=t1->tv_sec - (t0->tv_sec + 1);
+ diff->tv_usec=1000000 - d;
+
+ return(0);
+ }
+
+int r_timeval_add(t1,t2,sum)
+ struct timeval *t1;
+ struct timeval *t2;
+ struct timeval *sum;
+ {
+ long tv_sec,tv_usec,d;
+
+ tv_sec=t1->tv_sec + t2->tv_sec;
+
+ d=t1->tv_usec + t2->tv_usec;
+ if(d>1000000){
+ tv_sec++;
+ tv_usec=d-1000000;
+ }
+ else{
+ tv_usec=d;
+ }
+
+ sum->tv_sec=tv_sec;
+ sum->tv_usec=tv_usec;
+
+ return(0);
+ }
+
+int r_timeval_cmp(t1,t2)
+ struct timeval *t1;
+ struct timeval *t2;
+ {
+ if(t1->tv_sec>t2->tv_sec)
+ return(1);
+ if(t1->tv_sec<t2->tv_sec)
+ return(-1);
+ if(t1->tv_usec>t2->tv_usec)
+ return(1);
+ if(t1->tv_usec<t2->tv_usec)
+ return(-1);
+ return(0);
+ }
+
+
+UINT8 r_timeval2int(tv)
+ struct timeval *tv;
+ {
+ UINT8 r=0;
+
+ r=(tv->tv_sec);
+ r*=1000000;
+ r+=tv->tv_usec;
+
+ return r;
+ }
+
+int r_int2timeval(UINT8 t,struct timeval *tv)
+ {
+ tv->tv_sec=t/1000000;
+ tv->tv_usec=t%1000000;
+
+ return(0);
+ }
+
+UINT8 r_gettimeint()
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv,0);
+
+ return r_timeval2int(&tv);
+ }
+
+/* t1-t0 in microseconds */
+int r_timeval_diff_usec(struct timeval *t1, struct timeval *t0, INT8 *diff)
+ {
+ int r,_status;
+ int sign;
+ struct timeval tmp;
+
+ sign = 1;
+ if (r=r_timeval_diff(t1, t0, &tmp)) {
+ if (r == R_BAD_ARGS) {
+ sign = -1;
+ if (r=r_timeval_diff(t0, t1, &tmp))
+ ABORT(r);
+ }
+ }
+
+ /* 1 second = 1000 milliseconds
+ * 1 milliseconds = 1000 microseconds */
+
+ *diff = ((tmp.tv_sec * (1000*1000)) + tmp.tv_usec) * sign;
+
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
+/* t1-t0 in milliseconds */
+int r_timeval_diff_ms(struct timeval *t1, struct timeval *t0, INT8 *diff)
+ {
+ int r,_status;
+ int sign;
+ struct timeval tmp;
+
+ sign = 1;
+ if (r=r_timeval_diff(t1, t0, &tmp)) {
+ if (r == R_BAD_ARGS) {
+ sign = -1;
+ if (r=r_timeval_diff(t0, t1, &tmp))
+ ABORT(r);
+ }
+ }
+
+ /* 1 second = 1000 milliseconds
+ * 1 milliseconds = 1000 microseconds */
+
+ *diff = ((tmp.tv_sec * 1000) + (tmp.tv_usec / 1000)) * sign;
+
+ _status = 0;
+ abort:
+ return(_status);
+ }
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h
new file mode 100644
index 000000000..1ee1e778f
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h
@@ -0,0 +1,109 @@
+/**
+ r_time.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_time.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_time.h,v 1.4 2007/06/26 22:37:57 adamcain Exp $
+
+
+ ekr@rtfm.com Thu Mar 4 08:45:41 1999
+ */
+
+
+#ifndef _r_time_h
+#define _r_time_h
+
+#include <csi_platform.h>
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+int r_timeval_diff(struct timeval *t1,struct timeval *t0, struct timeval *diff);
+int r_timeval_add(struct timeval *t1,struct timeval *t2, struct timeval *sum);
+int r_timeval_cmp(struct timeval *t1,struct timeval *t2);
+
+UINT8 r_timeval2int(struct timeval *tv);
+int r_int2timeval(UINT8 t,struct timeval *tv);
+UINT8 r_gettimeint(void);
+
+/* t1-t0 in microseconds */
+int r_timeval_diff_usec(struct timeval *t1, struct timeval *t0, INT8 *diff);
+
+/* t1-t0 in milliseconds */
+int r_timeval_diff_ms(struct timeval *t1, struct timeval *t0, INT8 *diff);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_types.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_types.h
new file mode 100644
index 000000000..d00810a7a
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_types.h
@@ -0,0 +1,213 @@
+/**
+ r_types.h
+
+
+ Copyright (C) 2002-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ */
+
+/**
+ r_types.h
+
+
+ Copyright (C) 1999-2000 RTFM, Inc.
+ All Rights Reserved
+
+ This package is a SSLv3/TLS protocol analyzer written by Eric Rescorla
+ <ekr@rtfm.com> and licensed by RTFM, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+
+ This product includes software developed by Eric Rescorla for
+ RTFM, Inc.
+
+ 4. Neither the name of RTFM, Inc. nor the name of Eric Rescorla may be
+ used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY ERIC RESCORLA AND RTFM, INC. ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE.
+
+ $Id: r_types.h,v 1.2 2006/08/16 19:39:18 adamcain Exp $
+
+
+ ekr@rtfm.com Tue Dec 22 10:36:02 1998
+ */
+
+
+#ifndef _r_types_h
+#define _r_types_h
+
+/* Either define R_PLATFORM_INT_TYPES or be on a platform that
+ has stdint.h */
+#ifdef R_PLATFORM_INT_TYPES
+#include R_PLATFORM_INT_TYPES
+#else
+#include <stdint.h>
+#endif
+
+#ifndef R_DEFINED_INT2
+#ifndef SIZEOF_INT
+typedef short INT2;
+#else
+# if (SIZEOF_INT==2)
+typedef int INT2;
+# elif (SIZEOF_SHORT==2)
+typedef short INT2;
+# elif (SIZEOF_LONG==2)
+typedef long INT2;
+# else
+# error no type for INT2
+# endif
+#endif
+#else
+typedef R_DEFINED_INT2 INT2;
+#endif
+
+#ifndef R_DEFINED_UINT2
+#ifndef SIZEOF_UNSIGNED_INT
+typedef unsigned short UINT2;
+#else
+# if (SIZEOF_UNSIGNED_INT==2)
+typedef unsigned int UINT2;
+# elif (SIZEOF_UNSIGNED_SHORT==2)
+typedef unsigned short UINT2;
+# elif (SIZEOF_UNSIGNED_LONG==2)
+typedef unsigned long UINT2;
+# else
+# error no type for UINT2
+# endif
+#endif
+#else
+typedef R_DEFINED_UINT2 UINT2;
+#endif
+
+#ifndef R_DEFINED_INT4
+#ifndef SIZEOF_INT
+typedef int INT4;
+#else
+# if (SIZEOF_INT==4)
+typedef int INT4;
+# elif (SIZEOF_SHORT==4)
+typedef short INT4;
+# elif (SIZEOF_LONG==4)
+typedef long INT4;
+# else
+# error no type for INT4
+# endif
+#endif
+#else
+typedef R_DEFINED_INT4 INT4;
+#endif
+
+#ifndef R_DEFINED_UINT4
+#ifndef SIZEOF_UNSIGNED_INT
+typedef unsigned int UINT4;
+#else
+# if (SIZEOF_UNSIGNED_INT==4)
+typedef unsigned int UINT4;
+# elif (SIZEOF_UNSIGNED_SHORT==4)
+typedef unsigned short UINT4;
+# elif (SIZEOF_UNSIGNED_LONG==4)
+typedef unsigned long UINT4;
+# else
+# error no type for UINT4
+# endif
+#endif
+#else
+typedef R_DEFINED_UINT4 UINT4;
+#endif
+
+#ifndef R_DEFINED_INT8
+#ifndef SIZEOF_INT
+typedef long long INT8;
+#else
+# if (SIZEOF_INT==8)
+typedef int INT8;
+# elif (SIZEOF_SHORT==8)
+typedef short INT8;
+# elif (SIZEOF_LONG==8)
+typedef long INT8;
+# elif (SIZEOF_LONG_LONG==8)
+typedef long long INT8;
+# else
+# error no type for INT8
+# endif
+#endif
+#else
+typedef R_DEFINED_INT8 INT8;
+#endif
+
+#ifndef R_DEFINED_UINT8
+#ifndef SIZEOF_UNSIGNED_INT
+typedef unsigned long long UINT8;
+#else
+# if (SIZEOF_UNSIGNED_INT==8)
+typedef unsigned int UINT8;
+# elif (SIZEOF_UNSIGNED_SHORT==8)
+typedef unsigned short UINT8;
+# elif (SIZEOF_UNSIGNED_LONG==8)
+typedef unsigned long UINT8;
+# elif (SIZEOF_UNSIGNED_LONG_LONG==8)
+typedef unsigned long long UINT8;
+# else
+# error no type for UINT8
+# endif
+#endif
+#else
+typedef R_DEFINED_UINT8 UINT8;
+#endif
+
+#ifndef R_DEFINED_UCHAR
+typedef unsigned char UCHAR;
+#else
+typedef R_DEFINED_UCHAR UCHAR;
+#endif
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/p_buf.c b/media/mtransport/third_party/nrappkit/src/util/p_buf.c
new file mode 100644
index 000000000..8bb0e33bd
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/p_buf.c
@@ -0,0 +1,217 @@
+/**
+ p_buf.c
+
+
+ Copyright (C) 2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ All Rights Reserved.
+
+ ekr@rtfm.com Tue Nov 25 16:33:08 2003
+ */
+
+static char *RCSSTRING __UNUSED__ ="Id: p_buf.c,v 1.3 2004/01/03 22:13:53 ekr Exp $";
+
+#include <string.h>
+#include <stddef.h>
+#include "nr_common.h"
+#include "p_buf.h"
+
+
+static int nr_p_buf_destroy_chain(nr_p_buf_head *head);
+static int nr_p_buf_destroy(nr_p_buf *buf);
+
+int nr_p_buf_ctx_create(size,ctxp)
+ int size;
+ nr_p_buf_ctx **ctxp;
+ {
+ int _status;
+ nr_p_buf_ctx *ctx=0;
+
+ if(!(ctx=(nr_p_buf_ctx *)RCALLOC(sizeof(nr_p_buf_ctx))))
+ ABORT(R_NO_MEMORY);
+
+ ctx->buf_size=size;
+ STAILQ_INIT(&ctx->free_list);
+
+ *ctxp=ctx;
+ _status=0;
+ abort:
+ if(_status){
+ nr_p_buf_ctx_destroy(&ctx);
+ }
+ return(_status);
+ }
+
+int nr_p_buf_ctx_destroy(ctxp)
+ nr_p_buf_ctx **ctxp;
+ {
+ nr_p_buf_ctx *ctx;
+
+ if(!ctxp || !*ctxp)
+ return(0);
+
+ ctx=*ctxp;
+
+ nr_p_buf_destroy_chain(&ctx->free_list);
+
+ RFREE(ctx);
+ *ctxp=0;
+
+ return(0);
+ }
+
+int nr_p_buf_alloc(ctx,bufp)
+ nr_p_buf_ctx *ctx;
+ nr_p_buf **bufp;
+ {
+ int _status;
+ nr_p_buf *buf=0;
+
+ if(!STAILQ_EMPTY(&ctx->free_list)){
+ buf=STAILQ_FIRST(&ctx->free_list);
+ STAILQ_REMOVE_HEAD(&ctx->free_list,entry);
+ goto ok;
+ }
+ else {
+ if(!(buf=(nr_p_buf *)RCALLOC(sizeof(nr_p_buf))))
+ ABORT(R_NO_MEMORY);
+ if(!(buf->data=(UCHAR *)RMALLOC(ctx->buf_size)))
+ ABORT(R_NO_MEMORY);
+ buf->size=ctx->buf_size;
+ }
+
+ ok:
+ buf->r_offset=0;
+ buf->length=0;
+
+ *bufp=buf;
+ _status=0;
+ abort:
+ if(_status){
+ nr_p_buf_destroy(buf);
+ }
+ return(_status);
+ }
+
+int nr_p_buf_free(ctx,buf)
+ nr_p_buf_ctx *ctx;
+ nr_p_buf *buf;
+ {
+ STAILQ_INSERT_TAIL(&ctx->free_list,buf,entry);
+
+ return(0);
+ }
+
+int nr_p_buf_free_chain(ctx,head)
+ nr_p_buf_ctx *ctx;
+ nr_p_buf_head *head;
+ {
+ nr_p_buf *n1,*n2;
+
+ n1=STAILQ_FIRST(head);
+ while(n1){
+ n2=STAILQ_NEXT(n1,entry);
+
+ nr_p_buf_free(ctx,n1);
+
+ n1=n2;
+ }
+
+ return(0);
+ }
+
+
+int nr_p_buf_write_to_chain(ctx,chain,data,len)
+ nr_p_buf_ctx *ctx;
+ nr_p_buf_head *chain;
+ UCHAR *data;
+ UINT4 len;
+ {
+ int r,_status;
+ nr_p_buf *buf;
+
+ buf=STAILQ_LAST(chain,nr_p_buf_,entry);
+ while(len){
+ int towrite;
+
+ if(!buf){
+ if(r=nr_p_buf_alloc(ctx,&buf))
+ ABORT(r);
+ STAILQ_INSERT_TAIL(chain,buf,entry);
+ }
+
+ towrite=MIN(len,(buf->size-(buf->length+buf->r_offset)));
+
+ memcpy(buf->data+buf->length+buf->r_offset,data,towrite);
+ len-=towrite;
+ data+=towrite;
+ buf->length+=towrite;
+
+ r_log(LOG_COMMON,LOG_DEBUG,"Wrote %d bytes to buffer %p",towrite,buf);
+ buf=0;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+static int nr_p_buf_destroy_chain(head)
+ nr_p_buf_head *head;
+ {
+ nr_p_buf *n1,*n2;
+
+ n1=STAILQ_FIRST(head);
+ while(n1){
+ n2=STAILQ_NEXT(n1,entry);
+
+ nr_p_buf_destroy(n1);
+
+ n1=n2;
+ }
+
+ return(0);
+ }
+
+static int nr_p_buf_destroy(buf)
+ nr_p_buf *buf;
+ {
+ if(!buf)
+ return(0);
+
+ RFREE(buf->data);
+ RFREE(buf);
+
+ return(0);
+ }
+
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/p_buf.h b/media/mtransport/third_party/nrappkit/src/util/p_buf.h
new file mode 100644
index 000000000..29881960c
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/p_buf.h
@@ -0,0 +1,72 @@
+/**
+ p_buf.h
+
+
+ Copyright (C) 2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Tue Nov 25 15:58:37 2003
+ */
+
+
+#ifndef _p_buf_h
+#define _p_buf_h
+
+typedef struct nr_p_buf_ {
+ UCHAR *data; /*The pointer to the buffer where the data lives */
+ UINT4 size; /*The size of the buffer */
+ UINT4 r_offset; /*The offset into the buffer where the data starts
+ when reading */
+ UINT4 length; /*The length of the data portion */
+
+ STAILQ_ENTRY(nr_p_buf_) entry;
+} nr_p_buf;
+
+typedef STAILQ_HEAD(nr_p_buf_head_,nr_p_buf_) nr_p_buf_head;
+
+
+typedef struct nr_p_buf_ctx_ {
+ int buf_size;
+
+ nr_p_buf_head free_list;
+} nr_p_buf_ctx;
+
+int nr_p_buf_ctx_create(int size,nr_p_buf_ctx **ctxp);
+int nr_p_buf_ctx_destroy(nr_p_buf_ctx **ctxp);
+int nr_p_buf_alloc(nr_p_buf_ctx *ctx,nr_p_buf **bufp);
+int nr_p_buf_free(nr_p_buf_ctx *ctx,nr_p_buf *buf);
+int nr_p_buf_free_chain(nr_p_buf_ctx *ctx,nr_p_buf_head *chain);
+int nr_p_buf_write_to_chain(nr_p_buf_ctx *ctx,
+ nr_p_buf_head *chain,
+ UCHAR *data,UINT4 len);
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/util.c b/media/mtransport/third_party/nrappkit/src/util/util.c
new file mode 100644
index 000000000..31a245f45
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/util.c
@@ -0,0 +1,792 @@
+/**
+ util.c
+
+
+ Copyright (C) 2001-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Wed Dec 26 17:19:36 2001
+ */
+
+
+static char *RCSSTRING __UNUSED__ ="$Id: util.c,v 1.5 2007/11/21 00:09:13 adamcain Exp $";
+
+#ifndef WIN32
+#include <sys/uio.h>
+#include <pwd.h>
+#include <dirent.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef OPENSSL
+#include <openssl/evp.h>
+#endif
+#include "nr_common.h"
+#include "r_common.h"
+#include "registry.h"
+#include "util.h"
+#include "r_log.h"
+
+int nr_util_default_log_facility=LOG_COMMON;
+
+int nr_get_filename(base,name,namep)
+ char *base;
+ char *name;
+ char **namep;
+ {
+ int len=strlen(base)+strlen(name)+2;
+ char *ret=0;
+ int _status;
+
+ if(!(ret=(char *)RMALLOC(len)))
+ ABORT(R_NO_MEMORY);
+ if(base[strlen(base)-1]!='/'){
+ sprintf(ret,"%s/%s",base,name);
+ }
+ else{
+ sprintf(ret,"%s%s",base,name);
+ }
+ *namep=ret;
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+#if 0
+int read_RSA_private_key(base,name,keyp)
+ char *base;
+ char *name;
+ RSA **keyp;
+ {
+ char *keyfile=0;
+ BIO *bio=0;
+ FILE *fp=0;
+ RSA *rsa=0;
+ int r,_status;
+
+ /* Load the keyfile */
+ if(r=get_filename(base,name,&keyfile))
+ ABORT(r);
+ if(!(fp=fopen(keyfile,"r")))
+ ABORT(R_NOT_FOUND);
+ if(!(bio=BIO_new(BIO_s_file())))
+ ABORT(R_NO_MEMORY);
+ BIO_set_fp(bio,fp,BIO_NOCLOSE);
+
+ if(!(rsa=PEM_read_bio_RSAPrivateKey(bio,0,0,0)))
+ ABORT(R_NOT_FOUND);
+
+ *keyp=rsa;
+ _status=0;
+ abort:
+ return(_status);
+ }
+#endif
+
+
+void nr_errprintf_log(const char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+
+ r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
+
+ va_end(ap);
+ }
+
+void nr_errprintf_log2(void *ignore, const char *format,...)
+ {
+ va_list ap;
+
+ va_start(ap,format);
+
+ r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
+
+ va_end(ap);
+ }
+
+
+int nr_fwrite_all(FILE *fp,UCHAR *buf,int len)
+ {
+ int r,_status;
+
+ while(len){
+ r=fwrite(buf,1,len,fp);
+ if(r==0)
+ ABORT(R_IO_ERROR);
+
+ len-=r;
+ buf+=r;
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+int nr_read_data(fd,buf,len)
+ int fd;
+ char *buf;
+ int len;
+ {
+ int r,_status;
+
+ while(len){
+ r=NR_SOCKET_READ(fd,buf,len);
+ if(r<=0)
+ ABORT(R_EOD);
+
+ buf+=r;
+ len-=r;
+ }
+
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+
+#ifdef WIN32
+ // TODO
+#else
+int nr_drop_privileges(char *username)
+ {
+ int _status;
+
+ /* Drop privileges */
+ if ((getuid() == 0) || geteuid()==0) {
+ struct passwd *passwd;
+
+ if ((passwd = getpwnam(CAPTURE_USER)) == 0){
+ r_log(LOG_GENERIC,LOG_EMERG,"Couldn't get user %s",CAPTURE_USER);
+ ABORT(R_INTERNAL);
+ }
+
+ if(setuid(passwd->pw_uid)!=0){
+ r_log(LOG_GENERIC,LOG_EMERG,"Couldn't drop privileges");
+ ABORT(R_INTERNAL);
+ }
+ }
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+#endif
+
+int nr_bin2hex(UCHAR *in,int len,UCHAR *out)
+ {
+ while(len){
+ sprintf((char*)out,"%.2x",in[0] & 0xff);
+
+ in+=1;
+ out+=2;
+
+ len--;
+ }
+
+ return(0);
+ }
+
+int nr_hex_ascii_dump(Data *data)
+ {
+ UCHAR *ptr=data->data;
+ int len=data->len;
+
+ while(len){
+ int i;
+ int bytes=MIN(len,16);
+
+ for(i=0;i<bytes;i++)
+ printf("%.2x ",ptr[i]&255);
+ /* Fill */
+ for(i=0;i<(16-bytes);i++)
+ printf(" ");
+ printf(" ");
+
+ for(i=0;i<bytes;i++){
+ if(isprint(ptr[i]))
+ printf("%c",ptr[i]);
+ else
+ printf(".");
+ }
+ printf("\n");
+
+ len-=bytes;
+ ptr+=bytes;
+ }
+ return(0);
+ }
+
+#ifdef OPENSSL
+int nr_sha1_file(char *filename,UCHAR *out)
+ {
+ EVP_MD_CTX md_ctx;
+ FILE *fp=0;
+ int r,_status;
+ UCHAR buf[1024];
+ int out_len;
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ if(!(fp=fopen(filename,"r"))){
+ r_log(LOG_COMMON,LOG_ERR,"Couldn't open file %s",filename);
+ ABORT(R_NOT_FOUND);
+ }
+
+ EVP_DigestInit_ex(&md_ctx,EVP_sha1(),0);
+
+ while(1){
+ r=fread(buf,1,sizeof(buf),fp);
+
+ if(r<0){
+ r_log(LOG_COMMON,LOG_ERR,"Error reading from %s",filename);
+ ABORT(R_INTERNAL);
+ }
+
+ if(!r)
+ break;
+
+ EVP_DigestUpdate(&md_ctx,buf,r);
+ }
+
+ EVP_DigestFinal(&md_ctx,out,(unsigned int*)&out_len);
+ if(out_len!=20)
+ ABORT(R_INTERNAL);
+
+ _status=0;
+ abort:
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if(fp) fclose(fp);
+
+ return(_status);
+ }
+
+#endif
+
+#ifdef WIN32
+ // TODO
+#else
+
+#if 0
+
+#include <fts.h>
+
+int nr_rm_tree(char *path)
+ {
+ FTS *fts=0;
+ FTSENT *p;
+ int failed=0;
+ int _status;
+ char *argv[2];
+
+ argv[0]=path;
+ argv[1]=0;
+
+ if(!(fts=fts_open(argv,0,NULL))){
+ r_log_e(LOG_COMMON,LOG_ERR,"Couldn't open directory %s",path);
+ ABORT(R_FAILED);
+ }
+
+ while(p=fts_read(fts)){
+ switch(p->fts_info){
+ case FTS_D:
+ break;
+ case FTS_DOT:
+ break;
+ case FTS_ERR:
+ r_log_e(LOG_COMMON,LOG_ERR,"Problem reading %s",p->fts_path);
+ break;
+ default:
+ r_log(LOG_COMMON,LOG_DEBUG,"Removing %s",p->fts_path);
+ errno=0;
+ if(remove(p->fts_path)){
+ r_log_e(LOG_COMMON,LOG_ERR,"Problem removing %s",p->fts_path);
+ failed=1;
+ }
+ }
+ }
+
+ if(failed)
+ ABORT(R_FAILED);
+
+ _status=0;
+ abort:
+ if(fts) fts_close(fts);
+ return(_status);
+ }
+#endif
+
+int nr_write_pid_file(char *pid_filename)
+ {
+ FILE *fp;
+ int _status;
+
+ if(!pid_filename)
+ ABORT(R_BAD_ARGS);
+
+ unlink(pid_filename);
+
+ if(!(fp=fopen(pid_filename,"w"))){
+ r_log(LOG_GENERIC,LOG_CRIT,"Couldn't open PID file: %s",strerror(errno));
+ ABORT(R_NOT_FOUND);
+ }
+
+ fprintf(fp,"%d\n",getpid());
+
+ fclose(fp);
+
+ chmod(pid_filename,S_IRUSR | S_IRGRP | S_IROTH);
+
+ _status=0;
+ abort:
+ return(_status);
+ }
+#endif
+
+int nr_reg_uint4_fetch_and_check(NR_registry key, UINT4 min, UINT4 max, int log_fac, int die, UINT4 *val)
+ {
+ int r,_status;
+ UINT4 my_val;
+
+ if(r=NR_reg_get_uint4(key,&my_val)){
+ r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
+ ABORT(r);
+ }
+
+ if((min>0) && (my_val<min)){
+ r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (min = %lu)",key,(unsigned long)my_val,(unsigned long)min);
+ ABORT(R_BAD_DATA);
+ }
+
+ if(my_val>max){
+ r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (max = %lu)",key,(unsigned long)my_val,(unsigned long)max);
+ ABORT(R_BAD_DATA);
+ }
+
+ *val=my_val;
+ _status=0;
+
+ abort:
+ if(die && _status){
+ r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
+ exit(1);
+ }
+ return(_status);
+ }
+
+int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_fac, int die, UINT8 *val)
+ {
+ int r,_status;
+ UINT8 my_val;
+
+ if(r=NR_reg_get_uint8(key,&my_val)){
+ r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
+ ABORT(r);
+ }
+
+ if(my_val<min){
+ r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (min = %llu)",key,my_val,min);
+ ABORT(R_BAD_DATA);
+ }
+
+ if(my_val>max){
+ r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (max = %llu)",key,my_val,max);
+ ABORT(R_BAD_DATA);
+ }
+
+ *val=my_val;
+ _status=0;
+
+ abort:
+ if(die && _status){
+ r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
+ exit(1);
+ }
+ return(_status);
+ }
+
+#if defined(LINUX) || defined(WIN32)
+/*-
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(dst, src, siz)
+ char *dst;
+ const char *src;
+ size_t siz;
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
+
+#endif /* LINUX or WIN32 */
+
+#if defined(USE_OWN_INET_NTOP) || defined(WIN32)
+#include <errno.h>
+#ifdef WIN32
+#include <Ws2ipdef.h>
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+#else
+#include <sys/socket.h>
+#endif
+#define INET6
+
+/* inet_ntop implementation from NetBSD */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(NS_INADDRSZ)
+# define NS_INADDRSZ 4
+#endif
+#if !defined(NS_IN6ADDRSZ)
+# define NS_IN6ADDRSZ 16
+#endif
+#if !defined(NS_INT16SZ)
+# define NS_INT16SZ 2
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
+#ifdef INET6
+static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
+#endif /* INET6 */
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+#ifdef INET6
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+#endif /* INET6 */
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a unsigned char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char *src, char *dst, size_t size)
+{
+ char tmp[sizeof "255.255.255.255"];
+ int l;
+
+ l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
+ src[0], src[1], src[2], src[3]);
+ if (l <= 0 || (size_t) l >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strlcpy(dst, tmp, size);
+ return (dst);
+}
+
+#ifdef INET6
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const unsigned char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+ char *tp, *ep;
+ struct { int base, len; } best, cur;
+ unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+ int advance;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ best.len = -1; /* XXX gcc */
+ cur.len = -1; /* XXX gcc */
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ ep = tmp + sizeof(tmp);
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0) {
+ if (tp + 1 >= ep)
+ return (NULL);
+ *tp++ = ':';
+ }
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ advance = snprintf(tp, (size_t)(ep - tp), "%x", words[i]);
+ if (advance <= 0 || advance >= ep - tp)
+ return (NULL);
+ tp += advance;
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ)) {
+ if (tp + 1 >= ep)
+ return (NULL);
+ *tp++ = ':';
+ }
+ if (tp + 1 >= ep)
+ return (NULL);
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strlcpy(dst, tmp, size);
+ return (dst);
+}
+#endif /* INET6 */
+
+#ifdef WIN32
+/* Not exactly, will forgive stuff like <addr>:<port> */
+int inet_pton(int af, const char *src, void *dst)
+{
+ struct sockaddr_storage ss;
+ int addrlen = sizeof(ss);
+
+ if (af != AF_INET && af != AF_INET6) {
+ return -1;
+ }
+
+ if (!WSAStringToAddressA(src, af, NULL, (struct sockaddr*)&ss, &addrlen)) {
+ if (af == AF_INET) {
+ struct sockaddr_in *in = (struct sockaddr_in*)&ss;
+ memcpy(dst, &in->sin_addr, sizeof(struct in_addr));
+ } else {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss;
+ memcpy(dst, &in6->sin6_addr, sizeof(struct in6_addr));
+ }
+ return 1;
+ }
+ return 0;
+}
+#endif /* WIN32 */
+
+#endif
+
+#ifdef WIN32
+#include <time.h>
+/* this is only millisecond-accurate, but that should be OK */
+
+int gettimeofday(struct timeval *tv, void *tz)
+ {
+ SYSTEMTIME st;
+ FILETIME ft;
+ ULARGE_INTEGER u;
+
+ GetLocalTime (&st);
+
+ /* strangely, the FILETIME is the number of 100 nanosecond (0.1 us) intervals
+ * since the Epoch */
+ SystemTimeToFileTime(&st, &ft);
+ u.HighPart = ft.dwHighDateTime;
+ u.LowPart = ft.dwLowDateTime;
+
+ tv->tv_sec = (long) (u.QuadPart / 10000000L);
+ tv->tv_usec = (long) (st.wMilliseconds * 1000);;
+
+ return 0;
+ }
+
+#if _MSC_VER < 1900
+int snprintf(char *buffer, size_t n, const char *format, ...)
+{
+ va_list argp;
+ int ret;
+ va_start(argp, format);
+ ret = _vscprintf(format, argp);
+ vsnprintf_s(buffer, n, _TRUNCATE, format, argp);
+ va_end(argp);
+ return ret;
+}
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/src/util/util.h b/media/mtransport/third_party/nrappkit/src/util/util.h
new file mode 100644
index 000000000..869b72863
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/src/util/util.h
@@ -0,0 +1,74 @@
+/**
+ util.h
+
+
+ Copyright (C) 2001-2003, Network Resonance, Inc.
+ Copyright (C) 2006, Network Resonance, Inc.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of Network Resonance, Inc. nor the name of any
+ contributors to this software may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Wed Dec 26 17:20:23 2001
+ */
+
+
+#ifndef _util_h
+#define _util_h
+
+#include "registry.h"
+
+int nr_get_filename(char *base,char *name, char **namep);
+#if 0
+#include <openssl/ssl.h>
+
+int read_RSA_private_key(char *base, char *name,RSA **keyp);
+#endif
+void nr_errprintf_log(const char *fmt,...);
+void nr_errprintf_log2(void *ignore, const char *fmt,...);
+extern int nr_util_default_log_facility;
+
+int nr_read_data(int fd,char *buf,int len);
+int nr_drop_privileges(char *username);
+int nr_hex_ascii_dump(Data *data);
+int nr_fwrite_all(FILE *fp,UCHAR *buf,int len);
+int nr_sha1_file(char *filename,UCHAR *out);
+int nr_bin2hex(UCHAR *in,int len,UCHAR *out);
+int nr_rm_tree(char *path);
+int nr_write_pid_file(char *pid_filename);
+
+int nr_reg_uint4_fetch_and_check(NR_registry key, UINT4 min, UINT4 max, int log_fac, int die, UINT4 *val);
+int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_fac, int die, UINT8 *val);
+
+#ifdef WIN32
+int snprintf(char *buffer, size_t n, const char *format, ...);
+const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+int inet_pton(int af, const char *src, void *dst);
+#endif
+
+#endif
+
diff --git a/media/mtransport/third_party/nrappkit/upstream.diff b/media/mtransport/third_party/nrappkit/upstream.diff
new file mode 100644
index 000000000..df296677f
--- /dev/null
+++ b/media/mtransport/third_party/nrappkit/upstream.diff
@@ -0,0 +1,391 @@
+diff --git a/media/mtransport/third_party/nrappkit/src/event/async_wait.h b/media/mtransport/third_party/nrappkit/src/event/async_wait.h
+--- a/media/mtransport/third_party/nrappkit/src/event/async_wait.h
++++ b/media/mtransport/third_party/nrappkit/src/event/async_wait.h
+@@ -38,21 +38,21 @@
+
+
+ #ifndef _async_wait_h
+ #define _async_wait_h
+
+ #ifdef HAVE_SYS_TIME_H
+ #include <sys/time.h>
+ #endif
+ #include <csi_platform.h>
+
+-typedef void (*NR_async_cb)(int resource,int how,void *arg);
++typedef void (*NR_async_cb)(NR_SOCKET resource,int how,void *arg);
+
+ #define NR_ASYNC_WAIT_READ 0
+ #define NR_ASYNC_WAIT_WRITE 1
+
+
+ int NR_async_wait_init(void);
+ int NR_async_wait(NR_SOCKET sock, int how, NR_async_cb cb,void *cb_arg,
+ char *function,int line);
+ int NR_async_cancel(NR_SOCKET sock,int how);
+ int NR_async_schedule(NR_async_cb cb,void *arg,char *function,int line);
+diff --git a/media/mtransport/third_party/nrappkit/src/log/r_log.c b/media/mtransport/third_party/nrappkit/src/log/r_log.c
+--- a/media/mtransport/third_party/nrappkit/src/log/r_log.c
++++ b/media/mtransport/third_party/nrappkit/src/log/r_log.c
+@@ -33,28 +33,41 @@
+ POSSIBILITY OF SUCH DAMAGE.
+
+
+ ekr@rtfm.com Mon Dec 3 15:24:38 2001
+ */
+
+
+ static char *RCSSTRING __UNUSED__ ="$Id: r_log.c,v 1.10 2008/11/25 22:25:18 adamcain Exp $";
+
+
++#ifdef LINUX
++#define _BSD_SOURCE
++#endif
++
+ #include "r_log.h"
+ #include "hex.h"
++
+ #include <string.h>
++#include <errno.h>
++#ifndef _MSC_VER
++#include <strings.h>
++#include <syslog.h>
++#endif
+ #include <registry.h>
+ #include <time.h>
++
++
+ #include "nr_common.h"
+ #include "nr_reg_keys.h"
+
++
+ #define LOGGING_DEFAULT_LEVEL 5
+
+ int NR_LOG_LOGGING = 0;
+
+ static char *log_level_strings[]={
+ "EMERG",
+ "ALERT",
+ "CRIT",
+ "ERR",
+ "WARNING",
+diff --git a/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h
+--- a/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h
++++ b/media/mtransport/third_party/nrappkit/src/port/darwin/include/csi_platform.h
+@@ -37,17 +37,21 @@
+ */
+
+
+ #ifndef _platform_h
+ #define _platform_h
+
+ #include <unistd.h>
+
+ #define STDIO_BYTES_BUFFERED(fp) (fp->_r)
+
++#ifdef NR_SOCKET_IS_VOID_PTR
++typedef void* NR_SOCKET;
++#else
+ typedef int NR_SOCKET;
+ #define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
+ #define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
+ #define NR_SOCKET_CLOSE(sock) close(sock)
++#endif
+
+ #endif
+
+diff --git a/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h
+--- a/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h
++++ b/media/mtransport/third_party/nrappkit/src/port/linux/include/csi_platform.h
+@@ -35,17 +35,21 @@
+
+ ekr@rtfm.com Mon Dec 13 17:26:51 2004
+ */
+
+
+ #ifndef _platform_h
+ #define _platform_h
+
+ #include <linux_funcs.h>
+
++#ifdef NR_SOCKET_IS_VOID_PTR
++typedef void* NR_SOCKET;
++#else
+ typedef int NR_SOCKET;
+ #define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
+ #define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
+ #define NR_SOCKET_CLOSE(sock) close(sock)
++#endif
+
+ #endif
+
+diff --git a/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h b/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h
+--- a/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h
++++ b/media/mtransport/third_party/nrappkit/src/port/win32/include/csi_platform.h
+@@ -44,45 +44,51 @@
+ #define _WIN32_WINNT 0x0400 // This prevents weird "'TryEnterCriticalSection': identifier not found"
+ // compiler errors when poco/win32_mutex.h is included
+ #endif
+
+ #define UINT8 UBLAH_IGNORE_ME_PLEASE
+ #define INT8 BLAH_IGNORE_ME_PLEASE
+ #include <winsock2.h>
+ #undef UINT8
+ #undef INT8
+ #include <r_types.h>
++#include <errno.h>
+
+ #define strcasecmp _stricmp
+ #define strncasecmp _strnicmp
+-#define snprintf _snprintf
+
+ #define strcasestr stristr
+
+ /* Hack version of strlcpy (in util/util.c) */
+ size_t strlcat(char *dst, const char *src, size_t siz);
+
+ /* Hack version of getopt() (in util/getopt.c) */
+ int getopt(int argc, char *argv[], char *opstring);
+ extern char *optarg;
+ extern int optind;
+ extern int opterr;
+
+ /* Hack version of gettimeofday() (in util/util.c) */
+ int gettimeofday(struct timeval *tv, void *tz);
+
++#ifdef NR_SOCKET_IS_VOID_PTR
++typedef void* NR_SOCKET;
++#else
+ typedef SOCKET NR_SOCKET;
+ #define NR_SOCKET_READ(sock,buf,count) recv((sock),(buf),(count),0)
+ #define NR_SOCKET_WRITE(sock,buf,count) send((sock),(buf),(count),0)
+ #define NR_SOCKET_CLOSE(sock) closesocket(sock)
++#endif
+
++#ifndef EHOSTUNREACH
+ #define EHOSTUNREACH WSAEHOSTUNREACH
++#endif
+
+ #define LOG_EMERG 0
+ #define LOG_ALERT 1
+ #define LOG_CRIT 2
+ #define LOG_ERR 3
+ #define LOG_WARNING 4
+ #define LOG_NOTICE 5
+ #define LOG_INFO 6
+ #define LOG_DEBUG 7
+
+diff --git a/media/mtransport/third_party/nrappkit/src/registry/registry.c b/media/mtransport/third_party/nrappkit/src/registry/registry.c
+--- a/media/mtransport/third_party/nrappkit/src/registry/registry.c
++++ b/media/mtransport/third_party/nrappkit/src/registry/registry.c
+@@ -37,21 +37,22 @@
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ */
+
+ #include <assert.h>
+ #include <string.h>
+-#ifndef WIN32
++#ifndef _MSC_VER
++#include <strings.h>
+ #include <sys/param.h>
+ #include <netinet/in.h>
+ #endif
+ #ifdef OPENSSL
+ #include <openssl/ssl.h>
+ #endif
+ #include <ctype.h>
+ #include "registry.h"
+ #include "registry_int.h"
+ #include "registry_vtbl.h"
+diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c
+--- a/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c
++++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_crc32.c
+@@ -58,20 +58,21 @@
+ * the crc computation is finished. The crc should be complemented
+ * before transmission.
+ * The variable corresponding to the macro argument "crc" should
+ * be an unsigned long and should be preset to all ones for Ethernet
+ * use. An error-free packet will leave 0xDEBB20E3 in the crc.
+ * Spencer Garrett <srg@quick.com>
+ */
+
+
+ #include <sys/types.h>
++#include <r_types.h>
+
+ static char *RCSSTRING __UNUSED__ ="$Id: r_crc32.c,v 1.4 2008/11/26 03:22:02 adamcain Exp $";
+
+ #ifdef WIN32
+ #define u_int32_t UINT4
+ #endif
+
+ #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+ /* generated using the AUTODIN II polynomial
+diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h
+--- a/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h
++++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_macros.h
+@@ -118,20 +118,20 @@
+ #ifndef MIN
+ #define MIN(a,b) ((a)>(b))?(b):(a)
+ #endif
+
+ #ifndef MAX
+ #define MAX(a,b) ((b)>(a))?(b):(a)
+ #endif
+
+ #ifdef DEBUG
+ #define DBG(a) debug a
+-int debug(int class,char *format,...);
++int debug(int cls, char *format,...);
+ #else
+ #define DBG(a)
+ #endif
+
+ #define UNIMPLEMENTED do { fprintf(stderr,"%s:%d Function %s unimplemented\n",__FILE__,__LINE__,__FUNCTION__); abort(); } while(0)
+
+ #include "r_memory.h"
+
+ #endif
+diff --git a/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h
+--- a/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h
++++ b/media/mtransport/third_party/nrappkit/src/util/libekr/r_time.h
+@@ -77,35 +77,25 @@
+ $Id: r_time.h,v 1.4 2007/06/26 22:37:57 adamcain Exp $
+
+
+ ekr@rtfm.com Thu Mar 4 08:45:41 1999
+ */
+
+
+ #ifndef _r_time_h
+ #define _r_time_h
+
++#include <csi_platform.h>
+
+-#ifdef WIN32
+-# include <time.h>
+-#else
+-/* Cribbed from the autoconf doc */
+-# if TIME_WITH_SYS_TIME
+-# include <sys/time.h>
+-# include <time.h>
+-# else
+-# if HAVE_SYS_TIME_H
+-# include <sys/time.h>
+-# else
+-# include <time.h>
+-# endif
+-# endif
++#ifndef WIN32
++#include <sys/time.h>
++#include <time.h>
+ #endif
+
+ int r_timeval_diff(struct timeval *t1,struct timeval *t0, struct timeval *diff);
+ int r_timeval_add(struct timeval *t1,struct timeval *t2, struct timeval *sum);
+ int r_timeval_cmp(struct timeval *t1,struct timeval *t2);
+
+ UINT8 r_timeval2int(struct timeval *tv);
+ int r_int2timeval(UINT8 t,struct timeval *tv);
+ UINT8 r_gettimeint(void);
+
+diff --git a/media/mtransport/third_party/nrappkit/src/util/util.c b/media/mtransport/third_party/nrappkit/src/util/util.c
+--- a/media/mtransport/third_party/nrappkit/src/util/util.c
++++ b/media/mtransport/third_party/nrappkit/src/util/util.c
+@@ -292,20 +292,22 @@ int nr_sha1_file(char *filename,UCHAR *o
+
+ return(_status);
+ }
+
+ #endif
+
+ #ifdef WIN32
+ // TODO
+ #else
+
++#if 0
++
+ #include <fts.h>
+
+ int nr_rm_tree(char *path)
+ {
+ FTS *fts=0;
+ FTSENT *p;
+ int failed=0;
+ int _status;
+ char *argv[2];
+
+@@ -337,20 +339,21 @@ int nr_rm_tree(char *path)
+ }
+
+ if(failed)
+ ABORT(R_FAILED);
+
+ _status=0;
+ abort:
+ if(fts) fts_close(fts);
+ return(_status);
+ }
++#endif
+
+ int nr_write_pid_file(char *pid_filename)
+ {
+ FILE *fp;
+ int _status;
+
+ if(!pid_filename)
+ ABORT(R_BAD_ARGS);
+
+ unlink(pid_filename);
+@@ -739,12 +742,24 @@ int gettimeofday(struct timeval *tv, voi
+ * since the Epoch */
+ SystemTimeToFileTime(&st, &ft);
+ u.HighPart = ft.dwHighDateTime;
+ u.LowPart = ft.dwLowDateTime;
+
+ tv->tv_sec = (long) (u.QuadPart / 10000000L);
+ tv->tv_usec = (long) (st.wMilliseconds * 1000);;
+
+ return 0;
+ }
++
++int snprintf(char *buffer, size_t n, const char *format, ...)
++{
++ va_list argp;
++ int ret;
++ va_start(argp, format);
++ ret = _vscprintf(format, argp);
++ vsnprintf_s(buffer, n, _TRUNCATE, format, argp);
++ va_end(argp);
++ return ret;
++}
++
+ #endif
+
+diff --git a/media/mtransport/third_party/nrappkit/src/util/util.h b/media/mtransport/third_party/nrappkit/src/util/util.h
+--- a/media/mtransport/third_party/nrappkit/src/util/util.h
++++ b/media/mtransport/third_party/nrappkit/src/util/util.h
+@@ -57,12 +57,17 @@ int nr_drop_privileges(char *username);
+ int nr_hex_ascii_dump(Data *data);
+ int nr_fwrite_all(FILE *fp,UCHAR *buf,int len);
+ int nr_sha1_file(char *filename,UCHAR *out);
+ int nr_bin2hex(UCHAR *in,int len,UCHAR *out);
+ int nr_rm_tree(char *path);
+ int nr_write_pid_file(char *pid_filename);
+
+ int nr_reg_uint4_fetch_and_check(NR_registry key, UINT4 min, UINT4 max, int log_fac, int die, UINT4 *val);
+ int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_fac, int die, UINT8 *val);
+
++#ifdef WIN32
++int snprintf(char *buffer, size_t n, const char *format, ...);
++const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+ #endif
+
++#endif
++