Imported Upstream version 0.0.4
Sjoerd Simons
15 years ago
129 | 129 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
130 | 130 | NM = @NM@ |
131 | 131 | NMEDIT = @NMEDIT@ |
132 | OBJDUMP = @OBJDUMP@ | |
132 | 133 | OBJEXT = @OBJEXT@ |
133 | 134 | OTOOL = @OTOOL@ |
134 | 135 | OTOOL64 = @OTOOL64@ |
0 | nice 0.0.4 (2008-12-17) | |
1 | ======================== | |
2 | ||
3 | Fix compilation for 64bits systems | |
4 | Revert the use of netbuffer in the gstreamer elements | |
5 | Added support for pseudossl-tcp TURN relay for Google | |
6 | Added support for SOCKS5 proxy servers for TCP relaying | |
7 | Bug fixes and code cleaning | |
8 | ||
0 | 9 | nice 0.0.3 (2008-11-25) |
1 | 10 | ======================== |
2 | 11 |
434 | 434 | # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) |
435 | 435 | # --------------------------------------------------- |
436 | 436 | m4_define([lt_decl_varnames_tagged], |
437 | [_$0(m4_quote(m4_default([$1], [[, ]])), | |
438 | m4_quote(m4_if([$2], [], | |
439 | m4_quote(lt_decl_tag_varnames), | |
440 | m4_quote(m4_shift($@)))), | |
441 | m4_split(m4_normalize(m4_quote(_LT_TAGS))))]) | |
442 | m4_define([_lt_decl_varnames_tagged], [lt_combine([$1], [$2], [_], $3)]) | |
437 | [m4_assert([$# <= 2])dnl | |
438 | _$0(m4_quote(m4_default([$1], [[, ]])), | |
439 | m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), | |
440 | m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) | |
441 | m4_define([_lt_decl_varnames_tagged], | |
442 | [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) | |
443 | 443 | |
444 | 444 | |
445 | 445 | # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) |
999 | 999 | _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; |
1000 | 1000 | darwin1.*) |
1001 | 1001 | _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; |
1002 | darwin*) # darwin 5.x on | |
1002 | darwin*) # darwin 5.x on | |
1003 | 1003 | # if running on 10.5 or later, the deployment target defaults |
1004 | 1004 | # to the OS version, if on x86, and 10.4, the deployment |
1005 | # target defaults to 10.4. Don't you love it? | |
1005 | # target defaults to 10.4. Don't you love it? | |
1006 | 1006 | case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in |
1007 | 1007 | 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) |
1008 | 1008 | _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; |
1044 | 1044 | _LT_TAGVAR(whole_archive_flag_spec, $1)='' |
1045 | 1045 | _LT_TAGVAR(link_all_deplibs, $1)=yes |
1046 | 1046 | _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" |
1047 | if test "$GCC" = "yes"; then | |
1047 | case $cc_basename in | |
1048 | ifort*) _lt_dar_can_shared=yes ;; | |
1049 | *) _lt_dar_can_shared=$GCC ;; | |
1050 | esac | |
1051 | if test "$_lt_dar_can_shared" = "yes"; then | |
1048 | 1052 | output_verbose_link_cmd=echo |
1049 | 1053 | _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" |
1050 | 1054 | _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" |
1566 | 1570 | lt_cv_sys_max_cmd_len=-1; |
1567 | 1571 | ;; |
1568 | 1572 | |
1569 | cygwin* | mingw*) | |
1573 | cygwin* | mingw* | cegcc*) | |
1570 | 1574 | # On Win9x/ME, this test blows up -- it succeeds, but takes |
1571 | 1575 | # about 5 minutes as the teststring grows exponentially. |
1572 | 1576 | # Worse, since 9x/ME are not pre-emptively multitasking, |
1734 | 1738 | # endif |
1735 | 1739 | #endif |
1736 | 1740 | |
1737 | #ifdef __cplusplus | |
1738 | extern "C" void exit (int); | |
1739 | #endif | |
1740 | ||
1741 | 1741 | void fnord() { int i=42;} |
1742 | 1742 | int main () |
1743 | 1743 | { |
1753 | 1753 | else |
1754 | 1754 | puts (dlerror ()); |
1755 | 1755 | |
1756 | exit (status); | |
1756 | return status; | |
1757 | 1757 | }] |
1758 | 1758 | _LT_EOF |
1759 | 1759 | if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then |
1792 | 1792 | lt_cv_dlopen_self=yes |
1793 | 1793 | ;; |
1794 | 1794 | |
1795 | mingw* | pw32*) | |
1795 | mingw* | pw32* | cegcc*) | |
1796 | 1796 | lt_cv_dlopen="LoadLibrary" |
1797 | 1797 | lt_cv_dlopen_libs= |
1798 | 1798 | ;; |
2089 | 2089 | [AC_REQUIRE([AC_CANONICAL_HOST])dnl |
2090 | 2090 | m4_require([_LT_DECL_EGREP])dnl |
2091 | 2091 | m4_require([_LT_FILEUTILS_DEFAULTS])dnl |
2092 | m4_require([_LT_DECL_OBJDUMP])dnl | |
2092 | 2093 | m4_require([_LT_DECL_SED])dnl |
2093 | 2094 | AC_MSG_CHECKING([dynamic linker characteristics]) |
2094 | 2095 | m4_if([$1], |
2253 | 2254 | # libtool to hard-code these into programs |
2254 | 2255 | ;; |
2255 | 2256 | |
2256 | cygwin* | mingw* | pw32*) | |
2257 | cygwin* | mingw* | pw32* | cegcc*) | |
2257 | 2258 | version_type=windows |
2258 | 2259 | shrext_cmds=".dll" |
2259 | 2260 | need_version=no |
2260 | 2261 | need_lib_prefix=no |
2261 | 2262 | |
2262 | 2263 | case $GCC,$host_os in |
2263 | yes,cygwin* | yes,mingw* | yes,pw32*) | |
2264 | yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) | |
2264 | 2265 | library_names_spec='$libname.dll.a' |
2265 | 2266 | # DLL is installed to $(libdir)/../bin by postinstall_cmds |
2266 | 2267 | postinstall_cmds='base_file=`basename \${file}`~ |
2283 | 2284 | soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' |
2284 | 2285 | sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" |
2285 | 2286 | ;; |
2286 | mingw*) | |
2287 | mingw* | cegcc*) | |
2287 | 2288 | # MinGW DLLs use traditional 'lib' prefix |
2288 | 2289 | soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' |
2289 | 2290 | sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` |
2721 | 2722 | version_type=linux |
2722 | 2723 | need_lib_prefix=no |
2723 | 2724 | need_version=no |
2724 | library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' | |
2725 | library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' | |
2725 | 2726 | shlibpath_var=LD_LIBRARY_PATH |
2726 | 2727 | shlibpath_overrides_runpath=no |
2727 | 2728 | hardcode_into_libs=yes |
2745 | 2746 | if test "$GCC" = yes; then |
2746 | 2747 | variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" |
2747 | 2748 | fi |
2748 | ||
2749 | ||
2749 | 2750 | if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then |
2750 | 2751 | sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" |
2751 | 2752 | fi |
3022 | 3023 | # -- PORTME fill in with the dynamic library characteristics |
3023 | 3024 | m4_defun([_LT_CHECK_MAGIC_METHOD], |
3024 | 3025 | [m4_require([_LT_DECL_EGREP]) |
3026 | m4_require([_LT_DECL_OBJDUMP]) | |
3025 | 3027 | AC_CACHE_CHECK([how to recognize dependent libraries], |
3026 | 3028 | lt_cv_deplibs_check_method, |
3027 | 3029 | [lt_cv_file_magic_cmd='$MAGIC_CMD' |
3070 | 3072 | lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' |
3071 | 3073 | lt_cv_file_magic_cmd='$OBJDUMP -f' |
3072 | 3074 | fi |
3075 | ;; | |
3076 | ||
3077 | cegcc) | |
3078 | # use the weaker test based on 'objdump'. See mingw*. | |
3079 | lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' | |
3080 | lt_cv_file_magic_cmd='$OBJDUMP -f' | |
3073 | 3081 | ;; |
3074 | 3082 | |
3075 | 3083 | darwin* | rhapsody*) |
3383 | 3391 | aix*) |
3384 | 3392 | symcode='[[BCDT]]' |
3385 | 3393 | ;; |
3386 | cygwin* | mingw* | pw32*) | |
3394 | cygwin* | mingw* | pw32* | cegcc*) | |
3387 | 3395 | symcode='[[ABCDGISTW]]' |
3388 | 3396 | ;; |
3389 | 3397 | hpux*) |
3629 | 3637 | beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) |
3630 | 3638 | # PIC is the default for these OSes. |
3631 | 3639 | ;; |
3632 | mingw* | cygwin* | os2* | pw32*) | |
3640 | mingw* | cygwin* | os2* | pw32* | cegcc*) | |
3633 | 3641 | # This hack is so that the source file can tell whether it is being |
3634 | 3642 | # built for inclusion in a dll (and should export symbols for example). |
3635 | 3643 | # Although the cygwin gcc ignores -fPIC, still need this for old-style |
3656 | 3664 | fi |
3657 | 3665 | ;; |
3658 | 3666 | hpux*) |
3659 | # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but | |
3660 | # not for PA HP-UX. | |
3667 | # PIC is the default for 64-bit PA HP-UX, but not for 32-bit | |
3668 | # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag | |
3669 | # sets the default TLS model and affects inlining. | |
3661 | 3670 | case $host_cpu in |
3662 | hppa*64*|ia64*) | |
3671 | hppa*64*) | |
3663 | 3672 | ;; |
3664 | 3673 | *) |
3665 | 3674 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' |
3757 | 3766 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' |
3758 | 3767 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' |
3759 | 3768 | ;; |
3760 | icpc* | ecpc* ) | |
3761 | # Intel C++ | |
3769 | ecpc* ) | |
3770 | # old Intel C++ for x86_64 which still supported -KPIC. | |
3762 | 3771 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' |
3763 | 3772 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' |
3773 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' | |
3774 | ;; | |
3775 | icpc* ) | |
3776 | # Intel C++, used to be incompatible with GCC. | |
3777 | # ICC 10 doesn't accept -KPIC any more. | |
3778 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' | |
3779 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' | |
3764 | 3780 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' |
3765 | 3781 | ;; |
3766 | 3782 | pgCC* | pgcpp*) |
3928 | 3944 | # PIC is the default for these OSes. |
3929 | 3945 | ;; |
3930 | 3946 | |
3931 | mingw* | cygwin* | pw32* | os2*) | |
3947 | mingw* | cygwin* | pw32* | os2* | cegcc*) | |
3932 | 3948 | # This hack is so that the source file can tell whether it is being |
3933 | 3949 | # built for inclusion in a dll (and should export symbols for example). |
3934 | 3950 | # Although the cygwin gcc ignores -fPIC, still need this for old-style |
3944 | 3960 | ;; |
3945 | 3961 | |
3946 | 3962 | hpux*) |
3947 | # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but | |
3948 | # not for PA HP-UX. | |
3963 | # PIC is the default for 64-bit PA HP-UX, but not for 32-bit | |
3964 | # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag | |
3965 | # sets the default TLS model and affects inlining. | |
3949 | 3966 | case $host_cpu in |
3950 | hppa*64*|ia64*) | |
3967 | hppa*64*) | |
3951 | 3968 | # +Z the default |
3952 | 3969 | ;; |
3953 | 3970 | *) |
3997 | 4014 | fi |
3998 | 4015 | ;; |
3999 | 4016 | |
4000 | mingw* | cygwin* | pw32* | os2*) | |
4017 | mingw* | cygwin* | pw32* | os2* | cegcc*) | |
4001 | 4018 | # This hack is so that the source file can tell whether it is being |
4002 | 4019 | # built for inclusion in a dll (and should export symbols for example). |
4003 | 4020 | m4_if([$1], [GCJ], [], |
4028 | 4045 | |
4029 | 4046 | linux* | k*bsd*-gnu) |
4030 | 4047 | case $cc_basename in |
4031 | icc* | ecc* | ifort*) | |
4048 | # old Intel for x86_64 which still supported -KPIC. | |
4049 | ecc*) | |
4032 | 4050 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' |
4033 | 4051 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' |
4034 | 4052 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' |
4035 | 4053 | ;; |
4054 | # icc used to be incompatible with GCC. | |
4055 | # ICC 10 doesn't accept -KPIC any more. | |
4056 | icc* | ifort*) | |
4057 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' | |
4058 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' | |
4059 | _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' | |
4060 | ;; | |
4061 | # Lahey Fortran 8.1. | |
4062 | lf95*) | |
4063 | _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' | |
4064 | _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' | |
4065 | _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' | |
4066 | ;; | |
4036 | 4067 | pgcc* | pgf77* | pgf90* | pgf95*) |
4037 | 4068 | # Portland Group compilers (*not* the Pentium gcc compiler, |
4038 | 4069 | # which looks to be a dead project) |
4214 | 4245 | pw32*) |
4215 | 4246 | _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" |
4216 | 4247 | ;; |
4217 | cygwin* | mingw*) | |
4248 | cygwin* | mingw* | cegcc*) | |
4218 | 4249 | _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' |
4219 | 4250 | ;; |
4220 | 4251 | linux* | k*bsd*-gnu) |
4269 | 4300 | extract_expsyms_cmds= |
4270 | 4301 | |
4271 | 4302 | case $host_os in |
4272 | cygwin* | mingw* | pw32*) | |
4303 | cygwin* | mingw* | pw32* | cegcc*) | |
4273 | 4304 | # FIXME: the MSVC++ port hasn't been tested in a loooong time |
4274 | 4305 | # When not using gcc, we currently assume that we are using |
4275 | 4306 | # Microsoft Visual C++. |
4356 | 4387 | fi |
4357 | 4388 | ;; |
4358 | 4389 | |
4359 | cygwin* | mingw* | pw32*) | |
4390 | cygwin* | mingw* | pw32* | cegcc*) | |
4360 | 4391 | # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, |
4361 | 4392 | # as there is no search path for DLLs. |
4362 | 4393 | _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' |
4422 | 4453 | tmp_addflag=' -i_dynamic -nofor_main' ;; |
4423 | 4454 | ifc* | ifort*) # Intel Fortran compiler |
4424 | 4455 | tmp_addflag=' -nofor_main' ;; |
4456 | lf95*) # Lahey Fortran 8.1 | |
4457 | _LT_TAGVAR(whole_archive_flag_spec, $1)= | |
4458 | tmp_sharedflag='--shared' ;; | |
4425 | 4459 | xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) |
4426 | 4460 | tmp_sharedflag='-qmkshrobj' |
4427 | 4461 | tmp_addflag= ;; |
4654 | 4688 | fi |
4655 | 4689 | fi |
4656 | 4690 | |
4691 | _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' | |
4657 | 4692 | # It seems that -bexpall does not export symbols beginning with |
4658 | 4693 | # underscore (_), so it is better to generate a list of symbols to export. |
4659 | 4694 | _LT_TAGVAR(always_export_symbols, $1)=yes |
4708 | 4743 | _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic |
4709 | 4744 | ;; |
4710 | 4745 | |
4711 | cygwin* | mingw* | pw32*) | |
4746 | cygwin* | mingw* | pw32* | cegcc*) | |
4712 | 4747 | # When not using gcc, we currently assume that we are using |
4713 | 4748 | # Microsoft Visual C++. |
4714 | 4749 | # hardcode_libdir_flag_spec is actually meaningless, as there is |
4812 | 4847 | _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' |
4813 | 4848 | ;; |
4814 | 4849 | ia64*) |
4815 | _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' | |
4850 | _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' | |
4816 | 4851 | ;; |
4817 | 4852 | *) |
4818 | 4853 | _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' |
5593 | 5628 | fi |
5594 | 5629 | fi |
5595 | 5630 | |
5631 | _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' | |
5596 | 5632 | # It seems that -bexpall does not export symbols beginning with |
5597 | 5633 | # underscore (_), so it is better to generate a list of symbols to |
5598 | 5634 | # export. |
5651 | 5687 | esac |
5652 | 5688 | ;; |
5653 | 5689 | |
5654 | cygwin* | mingw* | pw32*) | |
5690 | cygwin* | mingw* | pw32* | cegcc*) | |
5655 | 5691 | # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, |
5656 | 5692 | # as there is no search path for DLLs. |
5657 | 5693 | _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' |
7032 | 7068 | ]) |
7033 | 7069 | |
7034 | 7070 | |
7071 | # _LT_DECL_OBJDUMP | |
7072 | # -------------- | |
7073 | # If we don't have a new enough Autoconf to choose the best objdump | |
7074 | # available, choose the one first in the user's PATH. | |
7075 | m4_defun([_LT_DECL_OBJDUMP], | |
7076 | [AC_CHECK_TOOL(OBJDUMP, objdump, false) | |
7077 | test -z "$OBJDUMP" && OBJDUMP=objdump | |
7078 | _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) | |
7079 | AC_SUBST([OBJDUMP]) | |
7080 | ]) | |
7081 | ||
7082 | ||
7035 | 7083 | # _LT_DECL_SED |
7036 | 7084 | # ------------ |
7037 | 7085 | # Check for a fully-functional sed program, that truncates |
7492 | 7540 | [enable_win32_dll=yes |
7493 | 7541 | |
7494 | 7542 | case $host in |
7495 | *-*-cygwin* | *-*-mingw* | *-*-pw32*) | |
7543 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) | |
7496 | 7544 | AC_CHECK_TOOL(AS, as, false) |
7497 | 7545 | AC_CHECK_TOOL(DLLTOOL, dlltool, false) |
7498 | 7546 | AC_CHECK_TOOL(OBJDUMP, objdump, false) |
7733 | 7781 | |
7734 | 7782 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- |
7735 | 7783 | # |
7736 | # Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. | |
7737 | # Written by Gary V. Vaughan, 2004 | |
7784 | # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. | |
7785 | # Written by Gary V. Vaughan, 2004 | |
7738 | 7786 | # |
7739 | 7787 | # This file is free software; the Free Software Foundation gives |
7740 | 7788 | # unlimited permission to copy and/or distribute it, with or without |
7741 | 7789 | # modifications, as long as this notice is preserved. |
7742 | 7790 | |
7743 | # serial 5 ltsugar.m4 | |
7791 | # serial 6 ltsugar.m4 | |
7744 | 7792 | |
7745 | 7793 | # This is to help aclocal find these macros, as it can't see m4_define. |
7746 | 7794 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) |
7796 | 7844 | # Produce a SEP delimited list of all paired combinations of elements of |
7797 | 7845 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list |
7798 | 7846 | # has the form PREFIXmINFIXSUFFIXn. |
7847 | # Needed until we can rely on m4_combine added in Autoconf 2.62. | |
7799 | 7848 | m4_define([lt_combine], |
7800 | [m4_if([$2], [], [], | |
7801 | [m4_if([$4], [], [], | |
7802 | [lt_join(m4_quote(m4_default([$1], [[, ]])), | |
7803 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_prefix, [$2], | |
7804 | [m4_foreach(_Lt_suffix, lt_car([m4_shiftn(3, $@)]), | |
7805 | [_Lt_prefix[]$3[]_Lt_suffix ])])))))])])dnl | |
7806 | ]) | |
7849 | [m4_if(m4_eval([$# > 3]), [1], | |
7850 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl | |
7851 | [[m4_foreach([_Lt_prefix], [$2], | |
7852 | [m4_foreach([_Lt_suffix], | |
7853 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, | |
7854 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) | |
7807 | 7855 | |
7808 | 7856 | |
7809 | 7857 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) |
7866 | 7914 | |
7867 | 7915 | # Generated from ltversion.in. |
7868 | 7916 | |
7869 | # serial 2976 ltversion.m4 | |
7917 | # serial 3012 ltversion.m4 | |
7870 | 7918 | # This file is part of GNU Libtool |
7871 | 7919 | |
7872 | m4_define([LT_PACKAGE_VERSION], [2.2.4]) | |
7873 | m4_define([LT_PACKAGE_REVISION], [1.2976]) | |
7920 | m4_define([LT_PACKAGE_VERSION], [2.2.6]) | |
7921 | m4_define([LT_PACKAGE_REVISION], [1.3012]) | |
7874 | 7922 | |
7875 | 7923 | AC_DEFUN([LTVERSION_VERSION], |
7876 | [macro_version='2.2.4' | |
7877 | macro_revision='1.2976' | |
7924 | [macro_version='2.2.6' | |
7925 | macro_revision='1.3012' | |
7878 | 7926 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) |
7879 | 7927 | _LT_DECL(, macro_revision, 0) |
7880 | 7928 | ]) |
173 | 173 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
174 | 174 | NM = @NM@ |
175 | 175 | NMEDIT = @NMEDIT@ |
176 | OBJDUMP = @OBJDUMP@ | |
176 | 177 | OBJEXT = @OBJEXT@ |
177 | 178 | OTOOL = @OTOOL@ |
178 | 179 | OTOOL64 = @OTOOL64@ |
49 | 49 | #include "conncheck.h" |
50 | 50 | #include "component.h" |
51 | 51 | #include "stun/stunagent.h" |
52 | #include "stun/usages/turn.h" | |
53 | #include "stun/usages/ice.h" | |
52 | 54 | |
53 | 55 | /* XXX: starting from ICE ID-18, Ta SHOULD now be set according |
54 | 56 | * to session bandwidth -> this is not yet implemented in NICE */ |
71 | 73 | GTimeVal next_check_tv; /**< property: next conncheck timestamp */ |
72 | 74 | gchar *stun_server_ip; /**< property: STUN server IP */ |
73 | 75 | guint stun_server_port; /**< property: STUN server port */ |
76 | gchar *proxy_ip; /**< property: Proxy server IP */ | |
77 | guint proxy_port; /**< property: Proxy server port */ | |
78 | NiceProxyType proxy_type; /**< property: Proxy type */ | |
79 | gchar *proxy_username; /**< property: Proxy username */ | |
80 | gchar *proxy_password; /**< property: Proxy password */ | |
74 | 81 | gboolean controlling_mode; /**< property: controlling-mode */ |
75 | 82 | guint timer_ta; /**< property: timer Ta */ |
76 | 83 | guint max_conn_checks; /**< property: max connectivity checks */ |
139 | 146 | Component *component, |
140 | 147 | NiceSocket *socket); |
141 | 148 | |
149 | StunUsageIceCompatibility agent_to_ice_compatibility (NiceAgent *agent); | |
150 | StunUsageTurnCompatibility agent_to_turn_compatibility (NiceAgent *agent); | |
151 | NiceTurnSocketCompatibility agent_to_turn_socket_compatibility (NiceAgent *agent); | |
152 | ||
142 | 153 | #endif /*_NICE_AGENT_PRIV_H */ |
87 | 87 | PROP_CONTROLLING_MODE, |
88 | 88 | PROP_FULL_MODE, |
89 | 89 | PROP_STUN_PACING_TIMER, |
90 | PROP_MAX_CONNECTIVITY_CHECKS | |
90 | PROP_MAX_CONNECTIVITY_CHECKS, | |
91 | PROP_PROXY_TYPE, | |
92 | PROP_PROXY_IP, | |
93 | PROP_PROXY_PORT, | |
94 | PROP_PROXY_USERNAME, | |
95 | PROP_PROXY_PASSWORD | |
91 | 96 | }; |
92 | 97 | |
93 | 98 | |
109 | 114 | Component *component); |
110 | 115 | static void priv_detach_stream_component (Stream *stream, Component *component); |
111 | 116 | |
112 | static StunUsageTurnCompatibility | |
113 | priv_agent_to_turn_compatibility (NiceAgent *agent) { | |
117 | StunUsageIceCompatibility | |
118 | agent_to_ice_compatibility (NiceAgent *agent) | |
119 | { | |
120 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
121 | STUN_USAGE_ICE_COMPATIBILITY_DRAFT19 : | |
122 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
123 | STUN_USAGE_ICE_COMPATIBILITY_GOOGLE : | |
124 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
125 | STUN_USAGE_ICE_COMPATIBILITY_MSN : STUN_USAGE_ICE_COMPATIBILITY_DRAFT19; | |
126 | } | |
127 | ||
128 | ||
129 | StunUsageTurnCompatibility | |
130 | agent_to_turn_compatibility (NiceAgent *agent) | |
131 | { | |
114 | 132 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? |
115 | 133 | STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 : |
116 | 134 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? |
117 | 135 | STUN_USAGE_TURN_COMPATIBILITY_GOOGLE : |
118 | 136 | agent->compatibility == NICE_COMPATIBILITY_MSN ? |
119 | 137 | STUN_USAGE_TURN_COMPATIBILITY_MSN : STUN_USAGE_TURN_COMPATIBILITY_DRAFT9; |
138 | } | |
139 | ||
140 | NiceTurnSocketCompatibility | |
141 | agent_to_turn_socket_compatibility (NiceAgent *agent) | |
142 | { | |
143 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
144 | NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 : | |
145 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
146 | NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE : | |
147 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
148 | NICE_TURN_SOCKET_COMPATIBILITY_MSN : | |
149 | NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9; | |
120 | 150 | } |
121 | 151 | |
122 | 152 | Stream *agent_find_stream (NiceAgent *agent, guint stream_id) |
273 | 303 | "Upper limit for the total number of connectivity checks performed", |
274 | 304 | 0, 0xffffffff, |
275 | 305 | 0, /* default set in init */ |
306 | G_PARAM_READWRITE)); | |
307 | ||
308 | g_object_class_install_property (gobject_class, PROP_PROXY_IP, | |
309 | g_param_spec_string ( | |
310 | "proxy-ip", | |
311 | "Proxy server IP", | |
312 | "The proxy server used to bypass a proxy firewall", | |
313 | NULL, | |
314 | G_PARAM_READWRITE)); | |
315 | ||
316 | g_object_class_install_property (gobject_class, PROP_PROXY_PORT, | |
317 | g_param_spec_uint ( | |
318 | "proxy-port", | |
319 | "Proxy server port", | |
320 | "The Proxy server used to bypass a proxy firewall", | |
321 | 1, 65536, | |
322 | 1, | |
323 | G_PARAM_READWRITE)); | |
324 | ||
325 | g_object_class_install_property (gobject_class, PROP_PROXY_TYPE, | |
326 | g_param_spec_uint ( | |
327 | "proxy-type", | |
328 | "Type of proxy to use", | |
329 | "The type of proxy set in the proxy-ip property", | |
330 | NICE_PROXY_TYPE_NONE, NICE_PROXY_TYPE_LAST, | |
331 | NICE_PROXY_TYPE_NONE, | |
332 | G_PARAM_READWRITE)); | |
333 | ||
334 | g_object_class_install_property (gobject_class, PROP_PROXY_USERNAME, | |
335 | g_param_spec_string ( | |
336 | "proxy-username", | |
337 | "Proxy server username", | |
338 | "The username used to authenticate with the proxy", | |
339 | NULL, | |
340 | G_PARAM_READWRITE)); | |
341 | ||
342 | g_object_class_install_property (gobject_class, PROP_PROXY_PASSWORD, | |
343 | g_param_spec_string ( | |
344 | "proxy-password", | |
345 | "Proxy server password", | |
346 | "The password used to authenticate with the proxy", | |
347 | NULL, | |
276 | 348 | G_PARAM_READWRITE)); |
277 | 349 | |
278 | 350 | /* install signals */ |
510 | 582 | /* XXX: should we prune the list of already existing checks? */ |
511 | 583 | break; |
512 | 584 | |
585 | case PROP_PROXY_IP: | |
586 | g_value_set_string (value, agent->proxy_ip); | |
587 | break; | |
588 | ||
589 | case PROP_PROXY_PORT: | |
590 | g_value_set_uint (value, agent->proxy_port); | |
591 | break; | |
592 | ||
593 | case PROP_PROXY_TYPE: | |
594 | g_value_set_uint (value, agent->proxy_type); | |
595 | break; | |
596 | ||
597 | case PROP_PROXY_USERNAME: | |
598 | g_value_set_string (value, agent->proxy_username); | |
599 | break; | |
600 | ||
601 | case PROP_PROXY_PASSWORD: | |
602 | g_value_set_string (value, agent->proxy_password); | |
603 | break; | |
604 | ||
513 | 605 | default: |
514 | 606 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
515 | 607 | } |
580 | 672 | agent->max_conn_checks = g_value_get_uint (value); |
581 | 673 | break; |
582 | 674 | |
675 | case PROP_PROXY_IP: | |
676 | agent->proxy_ip = g_value_dup_string (value); | |
677 | break; | |
678 | ||
679 | case PROP_PROXY_PORT: | |
680 | agent->proxy_port = g_value_get_uint (value); | |
681 | break; | |
682 | ||
683 | case PROP_PROXY_TYPE: | |
684 | agent->proxy_type = g_value_get_uint (value); | |
685 | break; | |
686 | ||
687 | case PROP_PROXY_USERNAME: | |
688 | agent->proxy_username = g_value_dup_string (value); | |
689 | break; | |
690 | ||
691 | case PROP_PROXY_PASSWORD: | |
692 | agent->proxy_password = g_value_dup_string (value); | |
693 | break; | |
694 | ||
583 | 695 | default: |
584 | 696 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
585 | 697 | } |
663 | 775 | rf_copy = g_strdup (remote_foundation); |
664 | 776 | |
665 | 777 | if (component->selected_pair.local->type == NICE_CANDIDATE_TYPE_RELAYED) { |
666 | nice_udp_turn_socket_set_peer (component->selected_pair.local->sockptr, | |
778 | nice_turn_socket_set_peer (component->selected_pair.local->sockptr, | |
667 | 779 | &component->selected_pair.remote->addr); |
668 | 780 | } |
669 | 781 | |
768 | 880 | cdisco = g_slice_new0 (CandidateDiscovery); |
769 | 881 | if (cdisco) { |
770 | 882 | modified_list = g_slist_append (agent->discovery_list, cdisco); |
771 | priv_agent_to_turn_compatibility (agent); | |
772 | 883 | |
773 | 884 | if (modified_list) { |
774 | 885 | Component *component = stream_find_component_by_id (stream, component_id); |
797 | 908 | } |
798 | 909 | cdisco->nicesock = socket; |
799 | 910 | } else { |
800 | cdisco->nicesock = nice_tcp_turn_socket_new (agent, | |
801 | component->ctx, | |
802 | &turn->server, | |
803 | priv_agent_to_turn_compatibility (agent)); | |
911 | NiceAddress proxy_server; | |
912 | socket = NULL; | |
913 | ||
914 | if (agent->proxy_type != NICE_PROXY_TYPE_NONE && | |
915 | agent->proxy_ip != NULL && | |
916 | nice_address_set_from_string (&proxy_server, agent->proxy_ip)) { | |
917 | nice_address_set_port (&proxy_server, agent->proxy_port); | |
918 | socket = nice_tcp_bsd_socket_new (agent, component->ctx, &proxy_server); | |
919 | ||
920 | if (socket && | |
921 | agent->proxy_type == NICE_PROXY_TYPE_SOCKS5) { | |
922 | socket = nice_socks5_socket_new (socket, &turn->server, | |
923 | agent->proxy_username, agent->proxy_password); | |
924 | } else { | |
925 | /* TODO add HTTP support */ | |
926 | nice_socket_free (socket); | |
927 | socket = NULL; | |
928 | } | |
929 | ||
930 | } | |
931 | if (socket == NULL) { | |
932 | socket = nice_tcp_bsd_socket_new (agent, component->ctx, &turn->server); | |
933 | } | |
934 | if (turn->type == NICE_RELAY_TYPE_TURN_TLS && | |
935 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { | |
936 | socket = nice_pseudossl_socket_new (agent, socket); | |
937 | } | |
938 | cdisco->nicesock = nice_tcp_turn_socket_new (agent, socket, | |
939 | agent_to_turn_socket_compatibility (agent)); | |
940 | ||
804 | 941 | if (!cdisco->nicesock) { |
805 | 942 | agent->discovery_list = g_slist_remove (modified_list, cdisco); |
806 | 943 | g_slice_free (CandidateDiscovery, cdisco); |
1310 | 1447 | |
1311 | 1448 | len = nice_socket_recv (socket, &from, buf_len, buf); |
1312 | 1449 | |
1450 | if (len <= 0) | |
1451 | return len; | |
1452 | ||
1313 | 1453 | #ifndef NDEBUG |
1314 | if (len >= 0) { | |
1454 | if (len > 0) { | |
1315 | 1455 | gchar tmpbuf[INET6_ADDRSTRLEN]; |
1316 | 1456 | nice_address_to_string (&from, tmpbuf); |
1317 | 1457 | nice_debug ("Agent %p : Packet received on local socket %u from [%s]:%u (%u octets).", agent, |
1319 | 1459 | } |
1320 | 1460 | #endif |
1321 | 1461 | |
1322 | if (len == 0) | |
1323 | return 0; | |
1324 | 1462 | |
1325 | 1463 | if ((guint)len > buf_len) |
1326 | 1464 | { |
1342 | 1480 | if (cand->type == NICE_CANDIDATE_TYPE_RELAYED && |
1343 | 1481 | cand->stream_id == stream->id && |
1344 | 1482 | cand->component_id == component->id) { |
1345 | len = nice_udp_turn_socket_parse_recv (cand->sockptr, &socket, | |
1483 | len = nice_turn_socket_parse_recv (cand->sockptr, &socket, | |
1346 | 1484 | &from, len, buf, &from, buf, len); |
1347 | 1485 | } |
1348 | 1486 | } |
1543 | 1681 | struct _IOCtx |
1544 | 1682 | { |
1545 | 1683 | GIOChannel *channel; |
1684 | GSource *source; | |
1546 | 1685 | NiceAgent *agent; |
1547 | 1686 | Stream *stream; |
1548 | 1687 | Component *component; |
1556 | 1695 | Stream *stream, |
1557 | 1696 | Component *component, |
1558 | 1697 | NiceSocket *socket, |
1559 | GIOChannel *channel) | |
1698 | GIOChannel *channel, | |
1699 | GSource *source) | |
1560 | 1700 | { |
1561 | 1701 | IOCtx *ctx; |
1562 | 1702 | |
1567 | 1707 | ctx->component = component; |
1568 | 1708 | ctx->socket = socket; |
1569 | 1709 | ctx->channel = channel; |
1710 | ctx->source = source; | |
1570 | 1711 | } |
1571 | 1712 | return ctx; |
1572 | 1713 | } |
1581 | 1722 | |
1582 | 1723 | static gboolean |
1583 | 1724 | nice_agent_g_source_cb ( |
1584 | GIOChannel *source, | |
1725 | GIOChannel *io, | |
1585 | 1726 | G_GNUC_UNUSED |
1586 | 1727 | GIOCondition condition, |
1587 | 1728 | gpointer data) |
1593 | 1734 | Stream *stream = ctx->stream; |
1594 | 1735 | Component *component = ctx->component; |
1595 | 1736 | gchar buf[MAX_BUFFER_SIZE]; |
1596 | guint len; | |
1737 | gint len; | |
1597 | 1738 | |
1598 | 1739 | g_static_rec_mutex_lock (&agent->mutex); |
1599 | 1740 | |
1600 | 1741 | /* note: dear compiler, these are for you: */ |
1601 | (void)source; | |
1742 | (void)io; | |
1602 | 1743 | |
1603 | 1744 | len = _nice_agent_recv (agent, stream, component, ctx->socket, |
1604 | 1745 | MAX_BUFFER_SIZE, buf); |
1605 | 1746 | |
1606 | if (len > 0 && component->g_source_io_cb) | |
1747 | if (len > 0 && component->g_source_io_cb) { | |
1607 | 1748 | component->g_source_io_cb (agent, stream->id, component->id, |
1608 | 1749 | len, buf, component->data); |
1750 | } else if (len < 0) { | |
1751 | GSource *source = ctx->source; | |
1752 | component->gsources = g_slist_remove (component->gsources, source); | |
1753 | g_source_destroy (source); | |
1754 | g_source_unref (source); | |
1755 | /* We don't close the socket because it would be way too complicated to | |
1756 | * take care of every path where the socket might still be used.. */ | |
1757 | nice_debug ("Agent %p: unable to recv from socket %p. Detaching", agent, | |
1758 | ctx->socket); | |
1759 | } | |
1609 | 1760 | |
1610 | 1761 | g_static_rec_mutex_unlock (&agent->mutex); |
1611 | 1762 | return TRUE; |
1632 | 1783 | /* note: without G_IO_ERR the glib mainloop goes into |
1633 | 1784 | * busyloop if errors are encountered */ |
1634 | 1785 | source = g_io_create_watch (io, G_IO_IN | G_IO_ERR); |
1635 | ctx = io_ctx_new (agent, stream, component, socket, io); | |
1786 | ctx = io_ctx_new (agent, stream, component, socket, io, source); | |
1636 | 1787 | g_source_set_callback (source, (GSourceFunc) nice_agent_g_source_cb, |
1637 | 1788 | ctx, (GDestroyNotify) io_ctx_free); |
1638 | 1789 | nice_debug ("Agent %p : Attach source %p (stream %u).", agent, source, stream->id); |
228 | 228 | } NiceCompatibility; |
229 | 229 | |
230 | 230 | /** |
231 | * NiceProxyType: | |
232 | * @NICE_PROXY_TYPE_NONE: Do not use a proxy | |
233 | * @NICE_PROXY_TYPE_SOCKS5: Use a SOCKS5 proxy | |
234 | * @NICE_PROXY_TYPE_HTTP: Use an HTTP proxy | |
235 | * @NICE_PROXY_TYPE_LAST: Dummy last proxy type | |
236 | * | |
237 | * An enum to specify which proxy type to use for relaying. | |
238 | * Note that the proxies will only be used with TCP TURN relaying. | |
239 | * See #NiceAgent:proxy-type | |
240 | */ | |
241 | typedef enum | |
242 | { | |
243 | NICE_PROXY_TYPE_NONE = 0, | |
244 | NICE_PROXY_TYPE_SOCKS5, | |
245 | NICE_PROXY_TYPE_HTTP, | |
246 | NICE_PROXY_TYPE_LAST = NICE_PROXY_TYPE_HTTP, | |
247 | } NiceProxyType; | |
248 | ||
249 | ||
250 | /** | |
231 | 251 | * NiceAgentRecvFunc: |
232 | 252 | * @agent: The #NiceAgent Object |
233 | 253 | * @stream_id: The id of the stream |
70 | 70 | now->tv_usec >= timer->tv_usec : |
71 | 71 | now->tv_sec >= timer->tv_sec; |
72 | 72 | } |
73 | ||
74 | static StunUsageIceCompatibility priv_agent_to_ice_compatibility (NiceAgent *agent) { | |
75 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
76 | STUN_USAGE_ICE_COMPATIBILITY_DRAFT19 : | |
77 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
78 | STUN_USAGE_ICE_COMPATIBILITY_GOOGLE : | |
79 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
80 | STUN_USAGE_ICE_COMPATIBILITY_MSN : STUN_USAGE_ICE_COMPATIBILITY_DRAFT19; | |
81 | } | |
82 | ||
83 | static StunUsageTurnCompatibility priv_agent_to_turn_compatibility (NiceAgent *agent) { | |
84 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
85 | STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 : | |
86 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
87 | STUN_USAGE_TURN_COMPATIBILITY_GOOGLE : | |
88 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
89 | STUN_USAGE_TURN_COMPATIBILITY_MSN : STUN_USAGE_TURN_COMPATIBILITY_DRAFT9; | |
90 | } | |
91 | ||
92 | 73 | |
93 | 74 | /** |
94 | 75 | * Finds the next connectivity check in WAITING state. |
575 | 556 | cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg, -1, |
576 | 557 | username, username_len, |
577 | 558 | password, password_len, |
578 | priv_agent_to_turn_compatibility (cand->agent)); | |
559 | agent_to_turn_compatibility (cand->agent)); | |
579 | 560 | |
580 | 561 | if (cand->agent->compatibility == NICE_COMPATIBILITY_MSN) { |
581 | 562 | g_free (cand->msn_turn_username); |
836 | 817 | |
837 | 818 | /* note: iterate the conncheck list for each component separately */ |
838 | 819 | for (c = 0; c < components; c++) { |
820 | Component *comp = NULL; | |
821 | agent_find_component (agent, stream->id, c+1, NULL, &comp); | |
822 | ||
839 | 823 | for (i = stream->conncheck_list; i; i = i->next) { |
840 | 824 | CandidateCheckPair *p = i->data; |
841 | 825 | |
845 | 829 | break; |
846 | 830 | } |
847 | 831 | } |
848 | /* note: all checks have failed */ | |
849 | if (i == NULL) | |
832 | ||
833 | /* note: all checks have failed | |
834 | * Set the component to FAILED only if it actually had remote candidates | |
835 | * that failed.. */ | |
836 | if (i == NULL && comp != NULL && comp->remote_candidates != NULL) | |
850 | 837 | agent_signal_component_state_change (agent, |
851 | 838 | stream->id, |
852 | 839 | (c + 1), /* component-id */ |
1322 | 1309 | uname, uname_len, password, password_len, |
1323 | 1310 | cand_use, controlling, priority, |
1324 | 1311 | agent->tie_breaker, |
1325 | priv_agent_to_ice_compatibility (agent)); | |
1312 | agent_to_ice_compatibility (agent)); | |
1326 | 1313 | |
1327 | 1314 | nice_debug ("Agent %p: conncheck created %d - %p", agent, buffer_len, pair->stun_message.buffer); |
1328 | 1315 | |
1687 | 1674 | |
1688 | 1675 | if (memcmp (discovery_id, response_id, sizeof(stun_transid_t)) == 0) { |
1689 | 1676 | res = stun_usage_ice_conncheck_process (resp, &sockaddr, &socklen, |
1690 | priv_agent_to_ice_compatibility (agent)); | |
1677 | agent_to_ice_compatibility (agent)); | |
1691 | 1678 | nice_debug ("Agent %p : stun_bind_process/conncheck for %p res %d " |
1692 | 1679 | "(controlling=%d).", agent, p, (int)res, agent->controlling_mode); |
1693 | 1680 | |
1921 | 1908 | if (memcmp (discovery_id, response_id, sizeof(stun_transid_t)) == 0) { |
1922 | 1909 | res = stun_usage_turn_process (resp, |
1923 | 1910 | &relayaddr, &relayaddrlen, &sockaddr, &socklen, &alternate, &alternatelen, |
1924 | &bandwidth, &lifetime, priv_agent_to_turn_compatibility (agent)); | |
1911 | &bandwidth, &lifetime, agent_to_turn_compatibility (agent)); | |
1925 | 1912 | nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.", |
1926 | 1913 | agent, d, (int)res); |
1927 | 1914 | |
2040 | 2027 | |
2041 | 2028 | if (memcmp (refresh_id, response_id, sizeof(stun_transid_t)) == 0) { |
2042 | 2029 | res = stun_usage_turn_refresh_process (resp, |
2043 | &lifetime, priv_agent_to_turn_compatibility (cand->agent)); | |
2030 | &lifetime, agent_to_turn_compatibility (cand->agent)); | |
2044 | 2031 | nice_debug ("Agent %p : stun_turn_refresh_process for %p res %d.", |
2045 | 2032 | agent, cand, (int)res); |
2046 | 2033 | if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS) { |
2401 | 2388 | res = stun_usage_ice_conncheck_create_reply (&agent->stun_agent, &req, |
2402 | 2389 | &msg, rbuf, &rbuf_len, &sockaddr, sizeof (sockaddr), |
2403 | 2390 | &control, agent->tie_breaker, |
2404 | priv_agent_to_ice_compatibility (agent)); | |
2391 | agent_to_ice_compatibility (agent)); | |
2405 | 2392 | |
2406 | 2393 | if (agent->compatibility == NICE_COMPATIBILITY_MSN) { |
2407 | 2394 | g_free (req.key); |
65 | 65 | now->tv_sec >= timer->tv_sec; |
66 | 66 | } |
67 | 67 | |
68 | static StunUsageTurnCompatibility | |
69 | priv_agent_to_turn_compatibility (NiceAgent *agent) { | |
70 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
71 | STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 : | |
72 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
73 | STUN_USAGE_TURN_COMPATIBILITY_GOOGLE : | |
74 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
75 | STUN_USAGE_TURN_COMPATIBILITY_MSN : STUN_USAGE_TURN_COMPATIBILITY_DRAFT9; | |
76 | } | |
77 | ||
78 | static NiceUdpTurnSocketCompatibility | |
79 | priv_agent_to_udp_turn_compatibility (NiceAgent *agent) { | |
80 | return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ? | |
81 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9 : | |
82 | agent->compatibility == NICE_COMPATIBILITY_GOOGLE ? | |
83 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE : | |
84 | agent->compatibility == NICE_COMPATIBILITY_MSN ? | |
85 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN : | |
86 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9; | |
87 | } | |
88 | ||
89 | 68 | /** |
90 | 69 | * Frees the CandidateDiscovery structure pointed to |
91 | 70 | * by 'user data'. Compatible with g_slist_foreach(). |
190 | 169 | cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg, 0, |
191 | 170 | username, username_len, |
192 | 171 | password, password_len, |
193 | priv_agent_to_turn_compatibility (agent)); | |
172 | agent_to_turn_compatibility (agent)); | |
194 | 173 | |
195 | 174 | if (buffer_len > 0) { |
196 | 175 | /* send the refresh twice since we won't do retransmissions */ |
309 | 288 | nice_address_get_port (&candidate->base_addr)); |
310 | 289 | |
311 | 290 | if (candidate->type == n->type && |
291 | candidate->stream_id == n->stream_id && | |
312 | 292 | nice_address_equal (&candidate->base_addr, &temp)) { |
313 | 293 | /* note: currently only one STUN/TURN server per stream at a |
314 | 294 | * time is supported, so there is no need to check |
550 | 530 | candidate->turn = turn; |
551 | 531 | |
552 | 532 | /* step: link to the base candidate+socket */ |
553 | relay_socket = nice_udp_turn_socket_new (agent, address, | |
533 | relay_socket = nice_turn_socket_new (agent, address, | |
554 | 534 | base_socket, &turn->server, |
555 | 535 | turn->username, turn->password, |
556 | priv_agent_to_udp_turn_compatibility (agent)); | |
536 | agent_to_turn_socket_compatibility (agent)); | |
557 | 537 | if (relay_socket) { |
558 | 538 | candidate->sockptr = relay_socket; |
559 | 539 | candidate->base_addr = base_socket->addr; |
859 | 839 | -1, -1, |
860 | 840 | username, username_len, |
861 | 841 | password, password_len, |
862 | priv_agent_to_turn_compatibility (agent)); | |
842 | agent_to_turn_compatibility (agent)); | |
863 | 843 | |
864 | 844 | if (agent->compatibility == NICE_COMPATIBILITY_MSN) { |
865 | 845 | g_free (cand->msn_turn_username); |
47 | 47 | #define USE_LOOPBACK 1 |
48 | 48 | #define TEST_GOOGLE 0 |
49 | 49 | |
50 | #define PROXY_IP "127.0.0.1" | |
51 | #define PROXY_PORT 1080 | |
52 | #define PROXY_TYPE NICE_PROXY_TYPE_SOCKS5 | |
53 | #define PROXY_USERNAME NULL | |
54 | #define PROXY_PASSWORD NULL | |
55 | ||
56 | ||
50 | 57 | #if TEST_GOOGLE |
51 | 58 | #define NICE_COMPATIBILITY NICE_COMPATIBILITY_GOOGLE |
52 | 59 | |
55 | 62 | #define USE_LOOPBACK 0 |
56 | 63 | |
57 | 64 | #define TURN_IP "209.85.163.126" |
58 | #define TURN_PORT 19295 | |
65 | #define TURN_PORT 443 | |
59 | 66 | #define TURN_USER "ih9ppiM0P6vN34DB" |
60 | 67 | #define TURN_PASS "" |
61 | 68 | #define TURN_USER2 TURN_USER |
62 | 69 | #define TURN_PASS2 TURN_PASS |
63 | #define TURN_TYPE NICE_RELAY_TYPE_TURN_UDP | |
70 | #define TURN_TYPE NICE_RELAY_TYPE_TURN_TLS | |
64 | 71 | |
65 | 72 | #endif |
66 | 73 | |
90 | 97 | #define TURN_PASS TSORG_PASS |
91 | 98 | #define TURN_USER2 TSORG_USER |
92 | 99 | #define TURN_PASS2 TSORG_PASS |
93 | #define TURN_TYPE NICE_RELAY_TYPE_TURN_UDP | |
100 | #define TURN_TYPE NICE_RELAY_TYPE_TURN_TCP | |
94 | 101 | #else |
95 | 102 | #define TURN_IP NUMB_IP |
96 | 103 | #define TURN_PORT NUMB_PORT |
153 | 160 | if (strncmp ("12345678", buf, 8)) |
154 | 161 | return; |
155 | 162 | |
156 | if ((int)user_data == 2) { | |
163 | if (GPOINTER_TO_UINT (user_data) == 2) { | |
157 | 164 | global_ragent_read = len; |
158 | 165 | g_main_loop_quit (global_mainloop); |
159 | 166 | } |
163 | 170 | { |
164 | 171 | g_debug ("test-fullmode:%s: %p", G_STRFUNC, data); |
165 | 172 | |
166 | if ((int)data == 1) | |
173 | if (GPOINTER_TO_UINT (data) == 1) | |
167 | 174 | global_lagent_gathering_done = TRUE; |
168 | else if ((int)data == 2) | |
175 | else if (GPOINTER_TO_UINT (data) == 2) | |
169 | 176 | global_ragent_gathering_done = TRUE; |
170 | 177 | |
171 | 178 | if (global_lagent_gathering_done && |
180 | 187 | { |
181 | 188 | g_debug ("test-fullmode:%s: %p", __func__, data); |
182 | 189 | |
183 | if ((int)data == 1) | |
190 | if (GPOINTER_TO_UINT (data) == 1) | |
184 | 191 | global_lagent_state[component_id - 1] = state; |
185 | else if ((int)data == 2) | |
192 | else if (GPOINTER_TO_UINT (data) == 2) | |
186 | 193 | global_ragent_state[component_id - 1] = state; |
187 | 194 | |
188 | 195 | if (state == NICE_COMPONENT_STATE_READY) |
217 | 224 | { |
218 | 225 | g_debug ("test-fullmode:%s: %p", __func__, data); |
219 | 226 | |
220 | if ((int)data == 1) | |
227 | if (GPOINTER_TO_UINT (data) == 1) | |
221 | 228 | ++global_lagent_cands; |
222 | else if ((int)data == 2) | |
229 | else if (GPOINTER_TO_UINT (data) == 2) | |
223 | 230 | ++global_ragent_cands; |
224 | 231 | |
225 | 232 | /* XXX: dear compiler, these are for you: */ |
239 | 246 | { |
240 | 247 | g_debug ("test-fullmode:%s: %p", __func__, data); |
241 | 248 | |
242 | if ((int)data == 1) | |
249 | if (GPOINTER_TO_UINT (data) == 1) | |
243 | 250 | global_lagent_ibr_received = TRUE; |
244 | else if ((int)data == 2) | |
251 | else if (GPOINTER_TO_UINT (data) == 2) | |
245 | 252 | global_ragent_ibr_received = TRUE; |
246 | 253 | |
247 | 254 | if (global_exit_when_ibr_received) |
350 | 357 | |
351 | 358 | /* step: attach to mainloop (needed to register the fds) */ |
352 | 359 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, |
353 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
360 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
361 | GUINT_TO_POINTER (1)); | |
354 | 362 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, |
355 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
363 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
364 | GUINT_TO_POINTER (1)); | |
356 | 365 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, |
357 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
366 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
367 | GUINT_TO_POINTER (2)); | |
358 | 368 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, |
359 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
369 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
370 | GUINT_TO_POINTER (2)); | |
360 | 371 | |
361 | 372 | /* step: run mainloop until local candidates are ready |
362 | 373 | * (see timer_cb() above) */ |
509 | 520 | |
510 | 521 | /* step: attach to mainloop (needed to register the fds) */ |
511 | 522 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, |
512 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
523 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
524 | GUINT_TO_POINTER (1)); | |
513 | 525 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, |
514 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
526 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
527 | GUINT_TO_POINTER (1)); | |
515 | 528 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, |
516 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
529 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
530 | GUINT_TO_POINTER (2)); | |
517 | 531 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, |
518 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
532 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
533 | GUINT_TO_POINTER (2)); | |
519 | 534 | |
520 | 535 | /* step: run mainloop until local candidates are ready |
521 | 536 | * (see timer_cb() above) */ |
671 | 686 | |
672 | 687 | /* step: attach to mainloop (needed to register the fds) */ |
673 | 688 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, |
674 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
689 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
690 | GUINT_TO_POINTER (1)); | |
675 | 691 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, |
676 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
692 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
693 | GUINT_TO_POINTER (2)); | |
677 | 694 | |
678 | 695 | /* step: run mainloop until local candidates are ready |
679 | 696 | * (see timer_cb() above) */ |
799 | 816 | |
800 | 817 | /* step: attach to mainloop (needed to register the fds) */ |
801 | 818 | nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, |
802 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1); | |
819 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
820 | GUINT_TO_POINTER (1)); | |
803 | 821 | nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, |
804 | g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2); | |
822 | g_main_loop_get_context (global_mainloop), cb_nice_recv, | |
823 | GUINT_TO_POINTER (2)); | |
805 | 824 | |
806 | 825 | /* step: run mainloop until local candidates are ready |
807 | 826 | * (see timer_cb() above) */ |
923 | 942 | nice_agent_add_local_address (ragent, &baseaddr); |
924 | 943 | #endif |
925 | 944 | |
926 | g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done", | |
927 | G_CALLBACK (cb_candidate_gathering_done), (gpointer)1); | |
928 | g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done", | |
929 | G_CALLBACK (cb_candidate_gathering_done), (gpointer)2); | |
930 | g_signal_connect (G_OBJECT (lagent), "component-state-changed", | |
931 | G_CALLBACK (cb_component_state_changed), (gpointer)1); | |
932 | g_signal_connect (G_OBJECT (ragent), "component-state-changed", | |
933 | G_CALLBACK (cb_component_state_changed), (gpointer)2); | |
934 | g_signal_connect (G_OBJECT (lagent), "new-selected-pair", | |
935 | G_CALLBACK (cb_new_selected_pair), (gpointer)1); | |
936 | g_signal_connect (G_OBJECT (ragent), "new-selected-pair", | |
937 | G_CALLBACK (cb_new_selected_pair), (gpointer)2); | |
938 | g_signal_connect (G_OBJECT (lagent), "new-candidate", | |
939 | G_CALLBACK (cb_new_candidate), (gpointer)1); | |
940 | g_signal_connect (G_OBJECT (ragent), "new-candidate", | |
941 | G_CALLBACK (cb_new_candidate), (gpointer)2); | |
942 | g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received", | |
943 | G_CALLBACK (cb_initial_binding_request_received), (gpointer)1); | |
944 | g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received", | |
945 | G_CALLBACK (cb_initial_binding_request_received), (gpointer)2); | |
945 | g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done", | |
946 | G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1)); | |
947 | g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done", | |
948 | G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2)); | |
949 | g_signal_connect (G_OBJECT (lagent), "component-state-changed", | |
950 | G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1)); | |
951 | g_signal_connect (G_OBJECT (ragent), "component-state-changed", | |
952 | G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2)); | |
953 | g_signal_connect (G_OBJECT (lagent), "new-selected-pair", | |
954 | G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1)); | |
955 | g_signal_connect (G_OBJECT (ragent), "new-selected-pair", | |
956 | G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2)); | |
957 | g_signal_connect (G_OBJECT (lagent), "new-candidate", | |
958 | G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1)); | |
959 | g_signal_connect (G_OBJECT (ragent), "new-candidate", | |
960 | G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2)); | |
961 | g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received", | |
962 | G_CALLBACK (cb_initial_binding_request_received), | |
963 | GUINT_TO_POINTER (1)); | |
964 | g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received", | |
965 | G_CALLBACK (cb_initial_binding_request_received), | |
966 | GUINT_TO_POINTER (2)); | |
946 | 967 | |
947 | 968 | stun_server = getenv ("NICE_STUN_SERVER"); |
948 | 969 | stun_server_port = getenv ("NICE_STUN_SERVER_PORT"); |
952 | 973 | g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL); |
953 | 974 | g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL); |
954 | 975 | } |
976 | ||
977 | g_object_set (G_OBJECT (lagent), "proxy-ip", PROXY_IP, NULL); | |
978 | g_object_set (G_OBJECT (lagent), "proxy-port", PROXY_PORT, NULL); | |
979 | g_object_set (G_OBJECT (lagent), "proxy-type", PROXY_TYPE, NULL); | |
980 | g_object_set (G_OBJECT (lagent), "proxy-username", PROXY_USERNAME, NULL); | |
981 | g_object_set (G_OBJECT (lagent), "proxy-password", PROXY_PASSWORD, NULL); | |
982 | g_object_set (G_OBJECT (ragent), "proxy-ip", PROXY_IP, NULL); | |
983 | g_object_set (G_OBJECT (ragent), "proxy-port", PROXY_PORT, NULL); | |
984 | g_object_set (G_OBJECT (ragent), "proxy-type", PROXY_TYPE, NULL); | |
985 | g_object_set (G_OBJECT (ragent), "proxy-username", PROXY_USERNAME, NULL); | |
986 | g_object_set (G_OBJECT (ragent), "proxy-password", PROXY_PASSWORD, NULL); | |
955 | 987 | |
956 | 988 | /* step: test setter/getter functions for properties */ |
957 | 989 | { |
964 | 996 | g_free (string); |
965 | 997 | g_object_get (G_OBJECT (lagent), "stun-server-port", &port, NULL); |
966 | 998 | g_assert (stun_server_port == NULL || port == (guint)atoi (stun_server_port)); |
999 | g_object_get (G_OBJECT (lagent), "proxy-ip", &string, NULL); | |
1000 | g_assert (strcmp (string, PROXY_IP) == 0); | |
1001 | g_free (string); | |
1002 | g_object_get (G_OBJECT (lagent), "proxy-port", &port, NULL); | |
1003 | g_assert (port == PROXY_PORT); | |
967 | 1004 | g_object_get (G_OBJECT (lagent), "controlling-mode", &mode, NULL); |
968 | 1005 | g_assert (mode == TRUE); |
969 | 1006 | g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 300, NULL); |
998 | 1035 | g_assert (global_lagent_cands == 2); |
999 | 1036 | g_assert (global_ragent_cands == 2); |
1000 | 1037 | |
1001 | #ifdef TEST_GOOGLE | |
1038 | #if TEST_GOOGLE | |
1002 | 1039 | return result; |
1003 | 1040 | #endif |
1004 | 1041 |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.61 for nice 0.0.3. | |
2 | # Generated by GNU Autoconf 2.61 for nice 0.0.4. | |
3 | 3 | # |
4 | 4 | # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, |
5 | 5 | # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. |
720 | 720 | # Identity of this package. |
721 | 721 | PACKAGE_NAME='nice' |
722 | 722 | PACKAGE_TARNAME='nice' |
723 | PACKAGE_VERSION='0.0.3' | |
724 | PACKAGE_STRING='nice 0.0.3' | |
723 | PACKAGE_VERSION='0.0.4' | |
724 | PACKAGE_STRING='nice 0.0.4' | |
725 | 725 | PACKAGE_BUGREPORT='' |
726 | 726 | |
727 | 727 | ac_unique_file="agent/agent.c" |
856 | 856 | ac_ct_DUMPBIN |
857 | 857 | NM |
858 | 858 | LN_S |
859 | OBJDUMP | |
859 | 860 | AR |
860 | 861 | RANLIB |
861 | 862 | lt_ECHO |
1400 | 1401 | # Omit some internal or obsolete options to make the list less imposing. |
1401 | 1402 | # This message is too long to be a string in the A/UX 3.1 sh. |
1402 | 1403 | cat <<_ACEOF |
1403 | \`configure' configures nice 0.0.3 to adapt to many kinds of systems. | |
1404 | \`configure' configures nice 0.0.4 to adapt to many kinds of systems. | |
1404 | 1405 | |
1405 | 1406 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1406 | 1407 | |
1470 | 1471 | |
1471 | 1472 | if test -n "$ac_init_help"; then |
1472 | 1473 | case $ac_init_help in |
1473 | short | recursive ) echo "Configuration of nice 0.0.3:";; | |
1474 | short | recursive ) echo "Configuration of nice 0.0.4:";; | |
1474 | 1475 | esac |
1475 | 1476 | cat <<\_ACEOF |
1476 | 1477 | |
1575 | 1576 | test -n "$ac_init_help" && exit $ac_status |
1576 | 1577 | if $ac_init_version; then |
1577 | 1578 | cat <<\_ACEOF |
1578 | nice configure 0.0.3 | |
1579 | nice configure 0.0.4 | |
1579 | 1580 | generated by GNU Autoconf 2.61 |
1580 | 1581 | |
1581 | 1582 | Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, |
1589 | 1590 | This file contains any messages produced by compilers while |
1590 | 1591 | running configure, to aid debugging if configure makes a mistake. |
1591 | 1592 | |
1592 | It was created by nice $as_me 0.0.3, which was | |
1593 | It was created by nice $as_me 0.0.4, which was | |
1593 | 1594 | generated by GNU Autoconf 2.61. Invocation command line was |
1594 | 1595 | |
1595 | 1596 | $ $0 $@ |
2284 | 2285 | |
2285 | 2286 | # Define the identity of the package. |
2286 | 2287 | PACKAGE='nice' |
2287 | VERSION='0.0.3' | |
2288 | VERSION='0.0.4' | |
2288 | 2289 | |
2289 | 2290 | |
2290 | 2291 | cat >>confdefs.h <<_ACEOF |
2434 | 2435 | |
2435 | 2436 | |
2436 | 2437 | # Set the libtool C/A/R version info |
2437 | NICE_CURRENT=1 | |
2438 | NICE_CURRENT=2 | |
2438 | 2439 | NICE_REVISION=0 |
2439 | NICE_AGE=1 | |
2440 | NICE_AGE=2 | |
2440 | 2441 | NICE_LIBVERSION=${NICE_CURRENT}:${NICE_REVISION}:${NICE_AGE} |
2441 | 2442 | NICE_LT_LDFLAGS="-version-info ${NICE_LIBVERSION}" |
2442 | 2443 | |
4438 | 4439 | |
4439 | 4440 | |
4440 | 4441 | |
4441 | macro_version='2.2.4' | |
4442 | macro_revision='1.2976' | |
4442 | macro_version='2.2.6' | |
4443 | macro_revision='1.3012' | |
4443 | 4444 | |
4444 | 4445 | |
4445 | 4446 | |
5029 | 5030 | else |
5030 | 5031 | lt_cv_nm_interface="BSD nm" |
5031 | 5032 | echo "int some_variable = 0;" > conftest.$ac_ext |
5032 | (eval echo "\"\$as_me:5033: $ac_compile\"" >&5) | |
5033 | (eval echo "\"\$as_me:5034: $ac_compile\"" >&5) | |
5033 | 5034 | (eval "$ac_compile" 2>conftest.err) |
5034 | 5035 | cat conftest.err >&5 |
5035 | (eval echo "\"\$as_me:5036: $NM \\\"conftest.$ac_objext\\\"\"" >&5) | |
5036 | (eval echo "\"\$as_me:5037: $NM \\\"conftest.$ac_objext\\\"\"" >&5) | |
5036 | 5037 | (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) |
5037 | 5038 | cat conftest.err >&5 |
5038 | (eval echo "\"\$as_me:5039: output\"" >&5) | |
5039 | (eval echo "\"\$as_me:5040: output\"" >&5) | |
5039 | 5040 | cat conftest.out >&5 |
5040 | 5041 | if $GREP 'External.*some_variable' conftest.out > /dev/null; then |
5041 | 5042 | lt_cv_nm_interface="MS dumpbin" |
5081 | 5082 | lt_cv_sys_max_cmd_len=-1; |
5082 | 5083 | ;; |
5083 | 5084 | |
5084 | cygwin* | mingw*) | |
5085 | cygwin* | mingw* | cegcc*) | |
5085 | 5086 | # On Win9x/ME, this test blows up -- it succeeds, but takes |
5086 | 5087 | # about 5 minutes as the teststring grows exponentially. |
5087 | 5088 | # Worse, since 9x/ME are not pre-emptively multitasking, |
5282 | 5283 | |
5283 | 5284 | |
5284 | 5285 | |
5286 | if test -n "$ac_tool_prefix"; then | |
5287 | # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. | |
5288 | set dummy ${ac_tool_prefix}objdump; ac_word=$2 | |
5289 | { echo "$as_me:$LINENO: checking for $ac_word" >&5 | |
5290 | echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } | |
5291 | if test "${ac_cv_prog_OBJDUMP+set}" = set; then | |
5292 | echo $ECHO_N "(cached) $ECHO_C" >&6 | |
5293 | else | |
5294 | if test -n "$OBJDUMP"; then | |
5295 | ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. | |
5296 | else | |
5297 | as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | |
5298 | for as_dir in $PATH | |
5299 | do | |
5300 | IFS=$as_save_IFS | |
5301 | test -z "$as_dir" && as_dir=. | |
5302 | for ac_exec_ext in '' $ac_executable_extensions; do | |
5303 | if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then | |
5304 | ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" | |
5305 | echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 | |
5306 | break 2 | |
5307 | fi | |
5308 | done | |
5309 | done | |
5310 | IFS=$as_save_IFS | |
5311 | ||
5312 | fi | |
5313 | fi | |
5314 | OBJDUMP=$ac_cv_prog_OBJDUMP | |
5315 | if test -n "$OBJDUMP"; then | |
5316 | { echo "$as_me:$LINENO: result: $OBJDUMP" >&5 | |
5317 | echo "${ECHO_T}$OBJDUMP" >&6; } | |
5318 | else | |
5319 | { echo "$as_me:$LINENO: result: no" >&5 | |
5320 | echo "${ECHO_T}no" >&6; } | |
5321 | fi | |
5322 | ||
5323 | ||
5324 | fi | |
5325 | if test -z "$ac_cv_prog_OBJDUMP"; then | |
5326 | ac_ct_OBJDUMP=$OBJDUMP | |
5327 | # Extract the first word of "objdump", so it can be a program name with args. | |
5328 | set dummy objdump; ac_word=$2 | |
5329 | { echo "$as_me:$LINENO: checking for $ac_word" >&5 | |
5330 | echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } | |
5331 | if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then | |
5332 | echo $ECHO_N "(cached) $ECHO_C" >&6 | |
5333 | else | |
5334 | if test -n "$ac_ct_OBJDUMP"; then | |
5335 | ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. | |
5336 | else | |
5337 | as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | |
5338 | for as_dir in $PATH | |
5339 | do | |
5340 | IFS=$as_save_IFS | |
5341 | test -z "$as_dir" && as_dir=. | |
5342 | for ac_exec_ext in '' $ac_executable_extensions; do | |
5343 | if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then | |
5344 | ac_cv_prog_ac_ct_OBJDUMP="objdump" | |
5345 | echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 | |
5346 | break 2 | |
5347 | fi | |
5348 | done | |
5349 | done | |
5350 | IFS=$as_save_IFS | |
5351 | ||
5352 | fi | |
5353 | fi | |
5354 | ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP | |
5355 | if test -n "$ac_ct_OBJDUMP"; then | |
5356 | { echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 | |
5357 | echo "${ECHO_T}$ac_ct_OBJDUMP" >&6; } | |
5358 | else | |
5359 | { echo "$as_me:$LINENO: result: no" >&5 | |
5360 | echo "${ECHO_T}no" >&6; } | |
5361 | fi | |
5362 | ||
5363 | if test "x$ac_ct_OBJDUMP" = x; then | |
5364 | OBJDUMP="false" | |
5365 | else | |
5366 | case $cross_compiling:$ac_tool_warned in | |
5367 | yes:) | |
5368 | { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools | |
5369 | whose name does not start with the host triplet. If you think this | |
5370 | configuration is useful to you, please write to autoconf@gnu.org." >&5 | |
5371 | echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools | |
5372 | whose name does not start with the host triplet. If you think this | |
5373 | configuration is useful to you, please write to autoconf@gnu.org." >&2;} | |
5374 | ac_tool_warned=yes ;; | |
5375 | esac | |
5376 | OBJDUMP=$ac_ct_OBJDUMP | |
5377 | fi | |
5378 | else | |
5379 | OBJDUMP="$ac_cv_prog_OBJDUMP" | |
5380 | fi | |
5381 | ||
5382 | test -z "$OBJDUMP" && OBJDUMP=objdump | |
5383 | ||
5384 | ||
5385 | ||
5386 | ||
5387 | ||
5388 | ||
5389 | ||
5390 | ||
5285 | 5391 | |
5286 | 5392 | { echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 |
5287 | 5393 | echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; } |
5334 | 5440 | lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' |
5335 | 5441 | lt_cv_file_magic_cmd='$OBJDUMP -f' |
5336 | 5442 | fi |
5443 | ;; | |
5444 | ||
5445 | cegcc) | |
5446 | # use the weaker test based on 'objdump'. See mingw*. | |
5447 | lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' | |
5448 | lt_cv_file_magic_cmd='$OBJDUMP -f' | |
5337 | 5449 | ;; |
5338 | 5450 | |
5339 | 5451 | darwin* | rhapsody*) |
5886 | 5998 | aix*) |
5887 | 5999 | symcode='[BCDT]' |
5888 | 6000 | ;; |
5889 | cygwin* | mingw* | pw32*) | |
6001 | cygwin* | mingw* | pw32* | cegcc*) | |
5890 | 6002 | symcode='[ABCDGISTW]' |
5891 | 6003 | ;; |
5892 | 6004 | hpux*) |
6145 | 6257 | ;; |
6146 | 6258 | *-*-irix6*) |
6147 | 6259 | # Find out which ABI we are using. |
6148 | echo '#line 6149 "configure"' > conftest.$ac_ext | |
6260 | echo '#line 6261 "configure"' > conftest.$ac_ext | |
6149 | 6261 | if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 |
6150 | 6262 | (eval $ac_compile) 2>&5 |
6151 | 6263 | ac_status=$? |
7518 | 7630 | -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
7519 | 7631 | -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
7520 | 7632 | -e 's:$: $lt_compiler_flag:'` |
7521 | (eval echo "\"\$as_me:7522: $lt_compile\"" >&5) | |
7633 | (eval echo "\"\$as_me:7634: $lt_compile\"" >&5) | |
7522 | 7634 | (eval "$lt_compile" 2>conftest.err) |
7523 | 7635 | ac_status=$? |
7524 | 7636 | cat conftest.err >&5 |
7525 | echo "$as_me:7526: \$? = $ac_status" >&5 | |
7637 | echo "$as_me:7638: \$? = $ac_status" >&5 | |
7526 | 7638 | if (exit $ac_status) && test -s "$ac_outfile"; then |
7527 | 7639 | # The compiler can only warn and ignore the option if not recognized |
7528 | 7640 | # So say no if there are warnings other than the usual output. |
7590 | 7702 | # PIC is the default for these OSes. |
7591 | 7703 | ;; |
7592 | 7704 | |
7593 | mingw* | cygwin* | pw32* | os2*) | |
7705 | mingw* | cygwin* | pw32* | os2* | cegcc*) | |
7594 | 7706 | # This hack is so that the source file can tell whether it is being |
7595 | 7707 | # built for inclusion in a dll (and should export symbols for example). |
7596 | 7708 | # Although the cygwin gcc ignores -fPIC, still need this for old-style |
7605 | 7717 | ;; |
7606 | 7718 | |
7607 | 7719 | hpux*) |
7608 | # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but | |
7609 | # not for PA HP-UX. | |
7720 | # PIC is the default for 64-bit PA HP-UX, but not for 32-bit | |
7721 | # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag | |
7722 | # sets the default TLS model and affects inlining. | |
7610 | 7723 | case $host_cpu in |
7611 | hppa*64*|ia64*) | |
7724 | hppa*64*) | |
7612 | 7725 | # +Z the default |
7613 | 7726 | ;; |
7614 | 7727 | *) |
7658 | 7771 | fi |
7659 | 7772 | ;; |
7660 | 7773 | |
7661 | mingw* | cygwin* | pw32* | os2*) | |
7774 | mingw* | cygwin* | pw32* | os2* | cegcc*) | |
7662 | 7775 | # This hack is so that the source file can tell whether it is being |
7663 | 7776 | # built for inclusion in a dll (and should export symbols for example). |
7664 | 7777 | lt_prog_compiler_pic='-DDLL_EXPORT' |
7688 | 7801 | |
7689 | 7802 | linux* | k*bsd*-gnu) |
7690 | 7803 | case $cc_basename in |
7691 | icc* | ecc* | ifort*) | |
7804 | # old Intel for x86_64 which still supported -KPIC. | |
7805 | ecc*) | |
7692 | 7806 | lt_prog_compiler_wl='-Wl,' |
7693 | 7807 | lt_prog_compiler_pic='-KPIC' |
7694 | 7808 | lt_prog_compiler_static='-static' |
7695 | 7809 | ;; |
7810 | # icc used to be incompatible with GCC. | |
7811 | # ICC 10 doesn't accept -KPIC any more. | |
7812 | icc* | ifort*) | |
7813 | lt_prog_compiler_wl='-Wl,' | |
7814 | lt_prog_compiler_pic='-fPIC' | |
7815 | lt_prog_compiler_static='-static' | |
7816 | ;; | |
7817 | # Lahey Fortran 8.1. | |
7818 | lf95*) | |
7819 | lt_prog_compiler_wl='-Wl,' | |
7820 | lt_prog_compiler_pic='--shared' | |
7821 | lt_prog_compiler_static='--static' | |
7822 | ;; | |
7696 | 7823 | pgcc* | pgf77* | pgf90* | pgf95*) |
7697 | 7824 | # Portland Group compilers (*not* the Pentium gcc compiler, |
7698 | 7825 | # which looks to be a dead project) |
7842 | 7969 | -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
7843 | 7970 | -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
7844 | 7971 | -e 's:$: $lt_compiler_flag:'` |
7845 | (eval echo "\"\$as_me:7846: $lt_compile\"" >&5) | |
7972 | (eval echo "\"\$as_me:7973: $lt_compile\"" >&5) | |
7846 | 7973 | (eval "$lt_compile" 2>conftest.err) |
7847 | 7974 | ac_status=$? |
7848 | 7975 | cat conftest.err >&5 |
7849 | echo "$as_me:7850: \$? = $ac_status" >&5 | |
7976 | echo "$as_me:7977: \$? = $ac_status" >&5 | |
7850 | 7977 | if (exit $ac_status) && test -s "$ac_outfile"; then |
7851 | 7978 | # The compiler can only warn and ignore the option if not recognized |
7852 | 7979 | # So say no if there are warnings other than the usual output. |
7947 | 8074 | -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
7948 | 8075 | -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
7949 | 8076 | -e 's:$: $lt_compiler_flag:'` |
7950 | (eval echo "\"\$as_me:7951: $lt_compile\"" >&5) | |
8077 | (eval echo "\"\$as_me:8078: $lt_compile\"" >&5) | |
7951 | 8078 | (eval "$lt_compile" 2>out/conftest.err) |
7952 | 8079 | ac_status=$? |
7953 | 8080 | cat out/conftest.err >&5 |
7954 | echo "$as_me:7955: \$? = $ac_status" >&5 | |
8081 | echo "$as_me:8082: \$? = $ac_status" >&5 | |
7955 | 8082 | if (exit $ac_status) && test -s out/conftest2.$ac_objext |
7956 | 8083 | then |
7957 | 8084 | # The compiler can only warn and ignore the option if not recognized |
8002 | 8129 | -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ |
8003 | 8130 | -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ |
8004 | 8131 | -e 's:$: $lt_compiler_flag:'` |
8005 | (eval echo "\"\$as_me:8006: $lt_compile\"" >&5) | |
8132 | (eval echo "\"\$as_me:8133: $lt_compile\"" >&5) | |
8006 | 8133 | (eval "$lt_compile" 2>out/conftest.err) |
8007 | 8134 | ac_status=$? |
8008 | 8135 | cat out/conftest.err >&5 |
8009 | echo "$as_me:8010: \$? = $ac_status" >&5 | |
8136 | echo "$as_me:8137: \$? = $ac_status" >&5 | |
8010 | 8137 | if (exit $ac_status) && test -s out/conftest2.$ac_objext |
8011 | 8138 | then |
8012 | 8139 | # The compiler can only warn and ignore the option if not recognized |
8106 | 8233 | extract_expsyms_cmds= |
8107 | 8234 | |
8108 | 8235 | case $host_os in |
8109 | cygwin* | mingw* | pw32*) | |
8236 | cygwin* | mingw* | pw32* | cegcc*) | |
8110 | 8237 | # FIXME: the MSVC++ port hasn't been tested in a loooong time |
8111 | 8238 | # When not using gcc, we currently assume that we are using |
8112 | 8239 | # Microsoft Visual C++. |
8193 | 8320 | fi |
8194 | 8321 | ;; |
8195 | 8322 | |
8196 | cygwin* | mingw* | pw32*) | |
8323 | cygwin* | mingw* | pw32* | cegcc*) | |
8197 | 8324 | # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, |
8198 | 8325 | # as there is no search path for DLLs. |
8199 | 8326 | hardcode_libdir_flag_spec='-L$libdir' |
8259 | 8386 | tmp_addflag=' -i_dynamic -nofor_main' ;; |
8260 | 8387 | ifc* | ifort*) # Intel Fortran compiler |
8261 | 8388 | tmp_addflag=' -nofor_main' ;; |
8389 | lf95*) # Lahey Fortran 8.1 | |
8390 | whole_archive_flag_spec= | |
8391 | tmp_sharedflag='--shared' ;; | |
8262 | 8392 | xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) |
8263 | 8393 | tmp_sharedflag='-qmkshrobj' |
8264 | 8394 | tmp_addflag= ;; |
8491 | 8621 | fi |
8492 | 8622 | fi |
8493 | 8623 | |
8624 | export_dynamic_flag_spec='${wl}-bexpall' | |
8494 | 8625 | # It seems that -bexpall does not export symbols beginning with |
8495 | 8626 | # underscore (_), so it is better to generate a list of symbols to export. |
8496 | 8627 | always_export_symbols=yes |
8657 | 8788 | export_dynamic_flag_spec=-rdynamic |
8658 | 8789 | ;; |
8659 | 8790 | |
8660 | cygwin* | mingw* | pw32*) | |
8791 | cygwin* | mingw* | pw32* | cegcc*) | |
8661 | 8792 | # When not using gcc, we currently assume that we are using |
8662 | 8793 | # Microsoft Visual C++. |
8663 | 8794 | # hardcode_libdir_flag_spec is actually meaningless, as there is |
8688 | 8819 | whole_archive_flag_spec='' |
8689 | 8820 | link_all_deplibs=yes |
8690 | 8821 | allow_undefined_flag="$_lt_dar_allow_undefined" |
8691 | if test "$GCC" = "yes"; then | |
8822 | case $cc_basename in | |
8823 | ifort*) _lt_dar_can_shared=yes ;; | |
8824 | *) _lt_dar_can_shared=$GCC ;; | |
8825 | esac | |
8826 | if test "$_lt_dar_can_shared" = "yes"; then | |
8692 | 8827 | output_verbose_link_cmd=echo |
8693 | 8828 | archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" |
8694 | 8829 | module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" |
8780 | 8915 | archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' |
8781 | 8916 | ;; |
8782 | 8917 | ia64*) |
8783 | archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' | |
8918 | archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' | |
8784 | 8919 | ;; |
8785 | 8920 | *) |
8786 | 8921 | archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' |
9518 | 9653 | # libtool to hard-code these into programs |
9519 | 9654 | ;; |
9520 | 9655 | |
9521 | cygwin* | mingw* | pw32*) | |
9656 | cygwin* | mingw* | pw32* | cegcc*) | |
9522 | 9657 | version_type=windows |
9523 | 9658 | shrext_cmds=".dll" |
9524 | 9659 | need_version=no |
9525 | 9660 | need_lib_prefix=no |
9526 | 9661 | |
9527 | 9662 | case $GCC,$host_os in |
9528 | yes,cygwin* | yes,mingw* | yes,pw32*) | |
9663 | yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) | |
9529 | 9664 | library_names_spec='$libname.dll.a' |
9530 | 9665 | # DLL is installed to $(libdir)/../bin by postinstall_cmds |
9531 | 9666 | postinstall_cmds='base_file=`basename \${file}`~ |
9548 | 9683 | soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' |
9549 | 9684 | sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" |
9550 | 9685 | ;; |
9551 | mingw*) | |
9686 | mingw* | cegcc*) | |
9552 | 9687 | # MinGW DLLs use traditional 'lib' prefix |
9553 | 9688 | soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' |
9554 | 9689 | sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` |
10029 | 10164 | version_type=linux |
10030 | 10165 | need_lib_prefix=no |
10031 | 10166 | need_version=no |
10032 | library_name_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' | |
10167 | library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' | |
10033 | 10168 | shlibpath_var=LD_LIBRARY_PATH |
10034 | 10169 | shlibpath_overrides_runpath=no |
10035 | 10170 | hardcode_into_libs=yes |
10206 | 10341 | lt_cv_dlopen_self=yes |
10207 | 10342 | ;; |
10208 | 10343 | |
10209 | mingw* | pw32*) | |
10344 | mingw* | pw32* | cegcc*) | |
10210 | 10345 | lt_cv_dlopen="LoadLibrary" |
10211 | 10346 | lt_cv_dlopen_libs= |
10212 | 10347 | ;; |
10763 | 10898 | lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 |
10764 | 10899 | lt_status=$lt_dlunknown |
10765 | 10900 | cat > conftest.$ac_ext <<_LT_EOF |
10766 | #line 10767 "configure" | |
10901 | #line 10902 "configure" | |
10767 | 10902 | #include "confdefs.h" |
10768 | 10903 | |
10769 | 10904 | #if HAVE_DLFCN_H |
10804 | 10939 | # endif |
10805 | 10940 | #endif |
10806 | 10941 | |
10807 | #ifdef __cplusplus | |
10808 | extern "C" void exit (int); | |
10809 | #endif | |
10810 | ||
10811 | 10942 | void fnord() { int i=42;} |
10812 | 10943 | int main () |
10813 | 10944 | { |
10823 | 10954 | else |
10824 | 10955 | puts (dlerror ()); |
10825 | 10956 | |
10826 | exit (status); | |
10957 | return status; | |
10827 | 10958 | } |
10828 | 10959 | _LT_EOF |
10829 | 10960 | if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 |
10863 | 10994 | lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 |
10864 | 10995 | lt_status=$lt_dlunknown |
10865 | 10996 | cat > conftest.$ac_ext <<_LT_EOF |
10866 | #line 10867 "configure" | |
10997 | #line 10998 "configure" | |
10867 | 10998 | #include "confdefs.h" |
10868 | 10999 | |
10869 | 11000 | #if HAVE_DLFCN_H |
10904 | 11035 | # endif |
10905 | 11036 | #endif |
10906 | 11037 | |
10907 | #ifdef __cplusplus | |
10908 | extern "C" void exit (int); | |
10909 | #endif | |
10910 | ||
10911 | 11038 | void fnord() { int i=42;} |
10912 | 11039 | int main () |
10913 | 11040 | { |
10923 | 11050 | else |
10924 | 11051 | puts (dlerror ()); |
10925 | 11052 | |
10926 | exit (status); | |
11053 | return status; | |
10927 | 11054 | } |
10928 | 11055 | _LT_EOF |
10929 | 11056 | if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 |
12019 | 12146 | { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \" |
12020 | 12147 | gstreamer-0.10 >= 0.10.0 |
12021 | 12148 | gstreamer-base-0.10 >= 0.10.0 |
12022 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12023 | 12149 | \"") >&5 |
12024 | 12150 | ($PKG_CONFIG --exists --print-errors " |
12025 | 12151 | gstreamer-0.10 >= 0.10.0 |
12026 | 12152 | gstreamer-base-0.10 >= 0.10.0 |
12027 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12028 | 12153 | ") 2>&5 |
12029 | 12154 | ac_status=$? |
12030 | 12155 | echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
12032 | 12157 | pkg_cv_GST_CFLAGS=`$PKG_CONFIG --cflags " |
12033 | 12158 | gstreamer-0.10 >= 0.10.0 |
12034 | 12159 | gstreamer-base-0.10 >= 0.10.0 |
12035 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12036 | 12160 | " 2>/dev/null` |
12037 | 12161 | else |
12038 | 12162 | pkg_failed=yes |
12049 | 12173 | { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \" |
12050 | 12174 | gstreamer-0.10 >= 0.10.0 |
12051 | 12175 | gstreamer-base-0.10 >= 0.10.0 |
12052 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12053 | 12176 | \"") >&5 |
12054 | 12177 | ($PKG_CONFIG --exists --print-errors " |
12055 | 12178 | gstreamer-0.10 >= 0.10.0 |
12056 | 12179 | gstreamer-base-0.10 >= 0.10.0 |
12057 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12058 | 12180 | ") 2>&5 |
12059 | 12181 | ac_status=$? |
12060 | 12182 | echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
12062 | 12184 | pkg_cv_GST_LIBS=`$PKG_CONFIG --libs " |
12063 | 12185 | gstreamer-0.10 >= 0.10.0 |
12064 | 12186 | gstreamer-base-0.10 >= 0.10.0 |
12065 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12066 | 12187 | " 2>/dev/null` |
12067 | 12188 | else |
12068 | 12189 | pkg_failed=yes |
12085 | 12206 | GST_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors " |
12086 | 12207 | gstreamer-0.10 >= 0.10.0 |
12087 | 12208 | gstreamer-base-0.10 >= 0.10.0 |
12088 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12089 | 12209 | "` |
12090 | 12210 | else |
12091 | 12211 | GST_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors " |
12092 | 12212 | gstreamer-0.10 >= 0.10.0 |
12093 | 12213 | gstreamer-base-0.10 >= 0.10.0 |
12094 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
12095 | 12214 | "` |
12096 | 12215 | fi |
12097 | 12216 | # Put the nasty error message in config.log where it belongs |
12704 | 12823 | # report actual input values of CONFIG_FILES etc. instead of their |
12705 | 12824 | # values after options handling. |
12706 | 12825 | ac_log=" |
12707 | This file was extended by nice $as_me 0.0.3, which was | |
12826 | This file was extended by nice $as_me 0.0.4, which was | |
12708 | 12827 | generated by GNU Autoconf 2.61. Invocation command line was |
12709 | 12828 | |
12710 | 12829 | CONFIG_FILES = $CONFIG_FILES |
12757 | 12876 | _ACEOF |
12758 | 12877 | cat >>$CONFIG_STATUS <<_ACEOF |
12759 | 12878 | ac_cs_version="\\ |
12760 | nice config.status 0.0.3 | |
12879 | nice config.status 0.0.4 | |
12761 | 12880 | configured by $0, generated by GNU Autoconf 2.61, |
12762 | 12881 | with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" |
12763 | 12882 | |
12899 | 13018 | lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' |
12900 | 13019 | reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' |
12901 | 13020 | reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' |
13021 | OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' | |
12902 | 13022 | deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' |
12903 | 13023 | file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' |
12904 | 13024 | AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' |
13004 | 13124 | lt_SP2NL \ |
13005 | 13125 | lt_NL2SP \ |
13006 | 13126 | reload_flag \ |
13127 | OBJDUMP \ | |
13007 | 13128 | deplibs_check_method \ |
13008 | 13129 | file_magic_cmd \ |
13009 | 13130 | AR \ |
13297 | 13418 | ac_ct_DUMPBIN!$ac_ct_DUMPBIN$ac_delim |
13298 | 13419 | NM!$NM$ac_delim |
13299 | 13420 | LN_S!$LN_S$ac_delim |
13421 | OBJDUMP!$OBJDUMP$ac_delim | |
13300 | 13422 | AR!$AR$ac_delim |
13301 | RANLIB!$RANLIB$ac_delim | |
13302 | 13423 | _ACEOF |
13303 | 13424 | |
13304 | 13425 | if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then |
13340 | 13461 | ac_delim='%!_!# ' |
13341 | 13462 | for ac_last_try in false false false false false :; do |
13342 | 13463 | cat >conf$$subs.sed <<_ACEOF |
13464 | RANLIB!$RANLIB$ac_delim | |
13343 | 13465 | lt_ECHO!$lt_ECHO$ac_delim |
13344 | 13466 | DSYMUTIL!$DSYMUTIL$ac_delim |
13345 | 13467 | NMEDIT!$NMEDIT$ac_delim |
13367 | 13489 | LTLIBOBJS!$LTLIBOBJS$ac_delim |
13368 | 13490 | _ACEOF |
13369 | 13491 | |
13370 | if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 25; then | |
13492 | if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 26; then | |
13371 | 13493 | break |
13372 | 13494 | elif $ac_last_try; then |
13373 | 13495 | { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 |
14056 | 14178 | reload_flag=$lt_reload_flag |
14057 | 14179 | reload_cmds=$lt_reload_cmds |
14058 | 14180 | |
14181 | # An object symbol dumper. | |
14182 | OBJDUMP=$lt_OBJDUMP | |
14183 | ||
14059 | 14184 | # Method to check whether dependent libraries are shared objects. |
14060 | 14185 | deplibs_check_method=$lt_deplibs_check_method |
14061 | 14186 |
2 | 2 | |
3 | 3 | dnl releases only do -Wall, cvs and prerelease does -Werror too |
4 | 4 | dnl use a three digit version number for releases, and four for cvs/prerelease |
5 | AC_INIT(nice, 0.0.3) | |
5 | AC_INIT(nice, 0.0.4) | |
6 | 6 | NICE_RELEASE="yes" |
7 | 7 | |
8 | 8 | AC_CONFIG_SRCDIR([agent/agent.c]) |
25 | 25 | ]) |
26 | 26 | |
27 | 27 | # Set the libtool C/A/R version info |
28 | NICE_CURRENT=1 | |
28 | NICE_CURRENT=2 | |
29 | 29 | NICE_REVISION=0 |
30 | NICE_AGE=1 | |
30 | NICE_AGE=2 | |
31 | 31 | NICE_LIBVERSION=${NICE_CURRENT}:${NICE_REVISION}:${NICE_AGE} |
32 | 32 | NICE_LT_LDFLAGS="-version-info ${NICE_LIBVERSION}" |
33 | 33 | AC_SUBST(NICE_LT_LDFLAGS) |
81 | 81 | PKG_CHECK_MODULES(GST, [ |
82 | 82 | gstreamer-0.10 >= 0.10.0 |
83 | 83 | gstreamer-base-0.10 >= 0.10.0 |
84 | gstreamer-netbuffer-0.10 >= 0.10.0 | |
85 | 84 | ], |
86 | 85 | [ |
87 | 86 | with_gstreamer=yes |
105 | 105 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
106 | 106 | NM = @NM@ |
107 | 107 | NMEDIT = @NMEDIT@ |
108 | OBJDUMP = @OBJDUMP@ | |
108 | 109 | OBJEXT = @OBJEXT@ |
109 | 110 | OTOOL = @OTOOL@ |
110 | 111 | OTOOL64 = @OTOOL64@ |
105 | 105 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
106 | 106 | NM = @NM@ |
107 | 107 | NMEDIT = @NMEDIT@ |
108 | OBJDUMP = @OBJDUMP@ | |
108 | 109 | OBJEXT = @OBJEXT@ |
109 | 110 | OTOOL = @OTOOL@ |
110 | 111 | OTOOL64 = @OTOOL64@ |
100 | 100 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
101 | 101 | NM = @NM@ |
102 | 102 | NMEDIT = @NMEDIT@ |
103 | OBJDUMP = @OBJDUMP@ | |
103 | 104 | OBJEXT = @OBJEXT@ |
104 | 105 | OTOOL = @OTOOL@ |
105 | 106 | OTOOL64 = @OTOOL64@ |
21 | 21 | </tr></table> |
22 | 22 | <div class="chapter" lang="en"> |
23 | 23 | <div class="titlepage"><div><div><h2 class="title"> |
24 | <a name="id2548431"></a>libnice's public API</h2></div></div></div> | |
24 | <a name="id2970939"></a>libnice's public API</h2></div></div></div> | |
25 | 25 | <div class="toc"><dl> |
26 | 26 | <dt> |
27 | 27 | <span class="refentrytitle"><a href="libnice-NiceAgent.html">NiceAgent</a></span><span class="refpurpose"> — ICE agent API implementation</span> |
33 | 33 | <ANCHOR id="NiceAgent--full-mode" href="libnice/libnice-NiceAgent.html#NiceAgent--full-mode"> |
34 | 34 | <ANCHOR id="NiceAgent--main-context" href="libnice/libnice-NiceAgent.html#NiceAgent--main-context"> |
35 | 35 | <ANCHOR id="NiceAgent--max-connectivity-checks" href="libnice/libnice-NiceAgent.html#NiceAgent--max-connectivity-checks"> |
36 | <ANCHOR id="NiceAgent--proxy-ip" href="libnice/libnice-NiceAgent.html#NiceAgent--proxy-ip"> | |
37 | <ANCHOR id="NiceAgent--proxy-password" href="libnice/libnice-NiceAgent.html#NiceAgent--proxy-password"> | |
38 | <ANCHOR id="NiceAgent--proxy-port" href="libnice/libnice-NiceAgent.html#NiceAgent--proxy-port"> | |
39 | <ANCHOR id="NiceAgent--proxy-type" href="libnice/libnice-NiceAgent.html#NiceAgent--proxy-type"> | |
40 | <ANCHOR id="NiceAgent--proxy-username" href="libnice/libnice-NiceAgent.html#NiceAgent--proxy-username"> | |
36 | 41 | <ANCHOR id="NiceAgent--stun-pacing-timer" href="libnice/libnice-NiceAgent.html#NiceAgent--stun-pacing-timer"> |
37 | 42 | <ANCHOR id="NiceAgent--stun-server" href="libnice/libnice-NiceAgent.html#NiceAgent--stun-server"> |
38 | 43 | <ANCHOR id="NiceAgent--stun-server-port" href="libnice/libnice-NiceAgent.html#NiceAgent--stun-server-port"> |
244 | 244 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--max-connectivity-checks" title='The "max-connectivity-checks" property'>max-connectivity-checks</a>" <a |
245 | 245 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" |
246 | 246 | >guint</a> : Read / Write |
247 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--proxy-ip" title='The "proxy-ip" property'>proxy-ip</a>" <a | |
248 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
249 | >gchar</a>* : Read / Write | |
250 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--proxy-password" title='The "proxy-password" property'>proxy-password</a>" <a | |
251 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
252 | >gchar</a>* : Read / Write | |
253 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--proxy-port" title='The "proxy-port" property'>proxy-port</a>" <a | |
254 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" | |
255 | >guint</a> : Read / Write | |
256 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--proxy-type" title='The "proxy-type" property'>proxy-type</a>" <a | |
257 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" | |
258 | >guint</a> : Read / Write | |
259 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--proxy-username" title='The "proxy-username" property'>proxy-username</a>" <a | |
260 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
261 | >gchar</a>* : Read / Write | |
247 | 262 | "<a class="link" href="libnice-NiceAgent.html#NiceAgent--stun-pacing-timer" title='The "stun-pacing-timer" property'>stun-pacing-timer</a>" <a |
248 | 263 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" |
249 | 264 | >guint</a> : Read / Write / Construct Only |
277 | 292 | <p> |
278 | 293 | </p> |
279 | 294 | <div class="example"> |
280 | <a name="id2565644"></a><p class="title"><b>Example 1. Simple example on how to use libnice</b></p> | |
295 | <a name="id3035523"></a><p class="title"><b>Example 1. Simple example on how to use libnice</b></p> | |
281 | 296 | <div class="example-contents"><pre class="programlisting"> |
282 | 297 | NiceAddress base_addr; |
283 | 298 | guint stream_id; |
420 | 435 | component_id for RTP/RTCP usages. |
421 | 436 | </p> |
422 | 437 | <div class="example"> |
423 | <a name="id2565973"></a><p class="title"><b>Example 2. Example of use.</b></p> | |
438 | <a name="id3035852"></a><p class="title"><b>Example 2. Example of use.</b></p> | |
424 | 439 | <div class="example-contents"><pre class="programlisting"> |
425 | 440 | nice_agent_send (agent, stream_id, NICE_COMPONENT_TYPE_RTP, len, buf); |
426 | 441 | </pre></div> |
559 | 574 | GTimeVal next_check_tv; /**< property: next conncheck timestamp */ |
560 | 575 | gchar *stun_server_ip; /**< property: STUN server IP */ |
561 | 576 | guint stun_server_port; /**< property: STUN server port */ |
577 | gchar *proxy_ip; /**< property: Proxy server IP */ | |
578 | guint proxy_port; /**< property: Proxy server port */ | |
579 | NiceProxyType proxy_type; /**< property: Proxy type */ | |
580 | gchar *proxy_username; /**< property: Proxy username */ | |
581 | gchar *proxy_password; /**< property: Proxy password */ | |
562 | 582 | gboolean controlling_mode; /**< property: controlling-mode */ |
563 | 583 | guint timer_ta; /**< property: timer Ta */ |
564 | 584 | guint max_conn_checks; /**< property: max connectivity checks */ |
1530 | 1550 | </div> |
1531 | 1551 | <hr> |
1532 | 1552 | <div class="refsect2" lang="en"> |
1553 | <a name="NiceAgent--proxy-ip"></a><h3>The <code class="literal">"proxy-ip"</code> property</h3> | |
1554 | <pre class="programlisting"> "proxy-ip" <a | |
1555 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
1556 | >gchar</a>* : Read / Write</pre> | |
1557 | <p>The proxy server used to bypass a proxy firewall.</p> | |
1558 | <p>Default value: NULL</p> | |
1559 | </div> | |
1560 | <hr> | |
1561 | <div class="refsect2" lang="en"> | |
1562 | <a name="NiceAgent--proxy-password"></a><h3>The <code class="literal">"proxy-password"</code> property</h3> | |
1563 | <pre class="programlisting"> "proxy-password" <a | |
1564 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
1565 | >gchar</a>* : Read / Write</pre> | |
1566 | <p>The password used to authenticate with the proxy.</p> | |
1567 | <p>Default value: NULL</p> | |
1568 | </div> | |
1569 | <hr> | |
1570 | <div class="refsect2" lang="en"> | |
1571 | <a name="NiceAgent--proxy-port"></a><h3>The <code class="literal">"proxy-port"</code> property</h3> | |
1572 | <pre class="programlisting"> "proxy-port" <a | |
1573 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" | |
1574 | >guint</a> : Read / Write</pre> | |
1575 | <p>The Proxy server used to bypass a proxy firewall.</p> | |
1576 | <p>Allowed values: [1,65536]</p> | |
1577 | <p>Default value: 1</p> | |
1578 | </div> | |
1579 | <hr> | |
1580 | <div class="refsect2" lang="en"> | |
1581 | <a name="NiceAgent--proxy-type"></a><h3>The <code class="literal">"proxy-type"</code> property</h3> | |
1582 | <pre class="programlisting"> "proxy-type" <a | |
1583 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" | |
1584 | >guint</a> : Read / Write</pre> | |
1585 | <p>The type of proxy set in the proxy-ip property.</p> | |
1586 | <p>Allowed values: <= 2</p> | |
1587 | <p>Default value: 0</p> | |
1588 | </div> | |
1589 | <hr> | |
1590 | <div class="refsect2" lang="en"> | |
1591 | <a name="NiceAgent--proxy-username"></a><h3>The <code class="literal">"proxy-username"</code> property</h3> | |
1592 | <pre class="programlisting"> "proxy-username" <a | |
1593 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar" | |
1594 | >gchar</a>* : Read / Write</pre> | |
1595 | <p>The username used to authenticate with the proxy.</p> | |
1596 | <p>Default value: NULL</p> | |
1597 | </div> | |
1598 | <hr> | |
1599 | <div class="refsect2" lang="en"> | |
1533 | 1600 | <a name="NiceAgent--stun-pacing-timer"></a><h3>The <code class="literal">"stun-pacing-timer"</code> property</h3> |
1534 | 1601 | <pre class="programlisting"> "stun-pacing-timer" <a |
1535 | 1602 | href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint" |
36 | 36 | <function name="The "full-mode" property" link="libnice-NiceAgent.html#NiceAgent--full-mode"/> |
37 | 37 | <function name="The "main-context" property" link="libnice-NiceAgent.html#NiceAgent--main-context"/> |
38 | 38 | <function name="The "max-connectivity-checks" property" link="libnice-NiceAgent.html#NiceAgent--max-connectivity-checks"/> |
39 | <function name="The "proxy-ip" property" link="libnice-NiceAgent.html#NiceAgent--proxy-ip"/> | |
40 | <function name="The "proxy-password" property" link="libnice-NiceAgent.html#NiceAgent--proxy-password"/> | |
41 | <function name="The "proxy-port" property" link="libnice-NiceAgent.html#NiceAgent--proxy-port"/> | |
42 | <function name="The "proxy-type" property" link="libnice-NiceAgent.html#NiceAgent--proxy-type"/> | |
43 | <function name="The "proxy-username" property" link="libnice-NiceAgent.html#NiceAgent--proxy-username"/> | |
39 | 44 | <function name="The "stun-pacing-timer" property" link="libnice-NiceAgent.html#NiceAgent--stun-pacing-timer"/> |
40 | 45 | <function name="The "stun-server" property" link="libnice-NiceAgent.html#NiceAgent--stun-server"/> |
41 | 46 | <function name="The "stun-server-port" property" link="libnice-NiceAgent.html#NiceAgent--stun-server-port"/> |
36 | 36 | <keyword type="" name="The "full-mode" property" link="libnice-NiceAgent.html#NiceAgent--full-mode"/> |
37 | 37 | <keyword type="" name="The "main-context" property" link="libnice-NiceAgent.html#NiceAgent--main-context"/> |
38 | 38 | <keyword type="" name="The "max-connectivity-checks" property" link="libnice-NiceAgent.html#NiceAgent--max-connectivity-checks"/> |
39 | <keyword type="" name="The "proxy-ip" property" link="libnice-NiceAgent.html#NiceAgent--proxy-ip"/> | |
40 | <keyword type="" name="The "proxy-password" property" link="libnice-NiceAgent.html#NiceAgent--proxy-password"/> | |
41 | <keyword type="" name="The "proxy-port" property" link="libnice-NiceAgent.html#NiceAgent--proxy-port"/> | |
42 | <keyword type="" name="The "proxy-type" property" link="libnice-NiceAgent.html#NiceAgent--proxy-type"/> | |
43 | <keyword type="" name="The "proxy-username" property" link="libnice-NiceAgent.html#NiceAgent--proxy-username"/> | |
39 | 44 | <keyword type="" name="The "stun-pacing-timer" property" link="libnice-NiceAgent.html#NiceAgent--stun-pacing-timer"/> |
40 | 45 | <keyword type="" name="The "stun-server" property" link="libnice-NiceAgent.html#NiceAgent--stun-server"/> |
41 | 46 | <keyword type="" name="The "stun-server-port" property" link="libnice-NiceAgent.html#NiceAgent--stun-server-port"/> |
155 | 155 | |
156 | 156 | </para> |
157 | 157 | |
158 | <!-- ##### ARG NiceAgent:proxy-ip ##### --> | |
159 | <para> | |
160 | ||
161 | </para> | |
162 | ||
163 | <!-- ##### ARG NiceAgent:proxy-password ##### --> | |
164 | <para> | |
165 | ||
166 | </para> | |
167 | ||
168 | <!-- ##### ARG NiceAgent:proxy-port ##### --> | |
169 | <para> | |
170 | ||
171 | </para> | |
172 | ||
173 | <!-- ##### ARG NiceAgent:proxy-type ##### --> | |
174 | <para> | |
175 | ||
176 | </para> | |
177 | ||
178 | <!-- ##### ARG NiceAgent:proxy-username ##### --> | |
179 | <para> | |
180 | ||
181 | </para> | |
182 | ||
158 | 183 | <!-- ##### ARG NiceAgent:stun-pacing-timer ##### --> |
159 | 184 | <para> |
160 | 185 |
109 | 109 | "<link linkend="NiceAgent--full-mode">full-mode</link>" <link linkend="gboolean">gboolean</link> : Read / Write / Construct Only |
110 | 110 | "<link linkend="NiceAgent--main-context">main-context</link>" <link linkend="gpointer">gpointer</link> : Read / Write / Construct Only |
111 | 111 | "<link linkend="NiceAgent--max-connectivity-checks">max-connectivity-checks</link>" <link linkend="guint">guint</link> : Read / Write |
112 | "<link linkend="NiceAgent--proxy-ip">proxy-ip</link>" <link linkend="gchar">gchar</link>* : Read / Write | |
113 | "<link linkend="NiceAgent--proxy-password">proxy-password</link>" <link linkend="gchar">gchar</link>* : Read / Write | |
114 | "<link linkend="NiceAgent--proxy-port">proxy-port</link>" <link linkend="guint">guint</link> : Read / Write | |
115 | "<link linkend="NiceAgent--proxy-type">proxy-type</link>" <link linkend="guint">guint</link> : Read / Write | |
116 | "<link linkend="NiceAgent--proxy-username">proxy-username</link>" <link linkend="gchar">gchar</link>* : Read / Write | |
112 | 117 | "<link linkend="NiceAgent--stun-pacing-timer">stun-pacing-timer</link>" <link linkend="guint">guint</link> : Read / Write / Construct Only |
113 | 118 | "<link linkend="NiceAgent--stun-server">stun-server</link>" <link linkend="gchar">gchar</link>* : Read / Write |
114 | 119 | "<link linkend="NiceAgent--stun-server-port">stun-server-port</link>" <link linkend="guint">guint</link> : Read / Write |
370 | 375 | GTimeVal next_check_tv; /**< property: next conncheck timestamp */ |
371 | 376 | gchar *stun_server_ip; /**< property: STUN server IP */ |
372 | 377 | guint stun_server_port; /**< property: STUN server port */ |
378 | gchar *proxy_ip; /**< property: Proxy server IP */ | |
379 | guint proxy_port; /**< property: Proxy server port */ | |
380 | NiceProxyType proxy_type; /**< property: Proxy type */ | |
381 | gchar *proxy_username; /**< property: Proxy username */ | |
382 | gchar *proxy_password; /**< property: Proxy password */ | |
373 | 383 | gboolean controlling_mode; /**< property: controlling-mode */ |
374 | 384 | guint timer_ta; /**< property: timer Ta */ |
375 | 385 | guint max_conn_checks; /**< property: max connectivity checks */ |
908 | 918 | <indexterm zone="NiceAgent--max-connectivity-checks"><primary>NiceAgent:max-connectivity-checks</primary></indexterm><programlisting> "max-connectivity-checks" <link linkend="guint">guint</link> : Read / Write</programlisting> |
909 | 919 | <para>Upper limit for the total number of connectivity checks performed.</para><para>Default value: 0</para> |
910 | 920 | </refsect2> |
921 | <refsect2 id="NiceAgent--proxy-ip"><title>The <literal>"proxy-ip"</literal> property</title> | |
922 | <indexterm zone="NiceAgent--proxy-ip"><primary>NiceAgent:proxy-ip</primary></indexterm><programlisting> "proxy-ip" <link linkend="gchar">gchar</link>* : Read / Write</programlisting> | |
923 | <para>The proxy server used to bypass a proxy firewall.</para><para>Default value: NULL</para> | |
924 | </refsect2> | |
925 | <refsect2 id="NiceAgent--proxy-password"><title>The <literal>"proxy-password"</literal> property</title> | |
926 | <indexterm zone="NiceAgent--proxy-password"><primary>NiceAgent:proxy-password</primary></indexterm><programlisting> "proxy-password" <link linkend="gchar">gchar</link>* : Read / Write</programlisting> | |
927 | <para>The password used to authenticate with the proxy.</para><para>Default value: NULL</para> | |
928 | </refsect2> | |
929 | <refsect2 id="NiceAgent--proxy-port"><title>The <literal>"proxy-port"</literal> property</title> | |
930 | <indexterm zone="NiceAgent--proxy-port"><primary>NiceAgent:proxy-port</primary></indexterm><programlisting> "proxy-port" <link linkend="guint">guint</link> : Read / Write</programlisting> | |
931 | <para>The Proxy server used to bypass a proxy firewall.</para><para>Allowed values: [1,65536]</para> | |
932 | <para>Default value: 1</para> | |
933 | </refsect2> | |
934 | <refsect2 id="NiceAgent--proxy-type"><title>The <literal>"proxy-type"</literal> property</title> | |
935 | <indexterm zone="NiceAgent--proxy-type"><primary>NiceAgent:proxy-type</primary></indexterm><programlisting> "proxy-type" <link linkend="guint">guint</link> : Read / Write</programlisting> | |
936 | <para>The type of proxy set in the proxy-ip property.</para><para>Allowed values: <= 2</para> | |
937 | <para>Default value: 0</para> | |
938 | </refsect2> | |
939 | <refsect2 id="NiceAgent--proxy-username"><title>The <literal>"proxy-username"</literal> property</title> | |
940 | <indexterm zone="NiceAgent--proxy-username"><primary>NiceAgent:proxy-username</primary></indexterm><programlisting> "proxy-username" <link linkend="gchar">gchar</link>* : Read / Write</programlisting> | |
941 | <para>The username used to authenticate with the proxy.</para><para>Default value: NULL</para> | |
942 | </refsect2> | |
911 | 943 | <refsect2 id="NiceAgent--stun-pacing-timer"><title>The <literal>"stun-pacing-timer"</literal> property</title> |
912 | 944 | <indexterm zone="NiceAgent--stun-pacing-timer"><primary>NiceAgent:stun-pacing-timer</primary></indexterm><programlisting> "stun-pacing-timer" <link linkend="guint">guint</link> : Read / Write / Construct Only</programlisting> |
913 | 945 | <para>Timer 'Ta' (msecs) used in the IETF ICE specification for pacing candidate gathering and sending of connectivity checks.</para><para>Allowed values: >= 1</para> |
134 | 134 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
135 | 135 | NM = @NM@ |
136 | 136 | NMEDIT = @NMEDIT@ |
137 | OBJDUMP = @OBJDUMP@ | |
137 | 138 | OBJEXT = @OBJEXT@ |
138 | 139 | OTOOL = @OTOOL@ |
139 | 140 | OTOOL64 = @OTOOL64@ |
194 | 194 | { |
195 | 195 | GstBaseSrc *basesrc = GST_BASE_SRC (data); |
196 | 196 | GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc); |
197 | GstNetBuffer *mybuf; | |
198 | 197 | |
199 | 198 | GST_LOG_OBJECT (agent, "Got buffer, getting out of the main loop"); |
200 | 199 | |
201 | mybuf = gst_netbuffer_new (); | |
202 | GST_BUFFER_MALLOCDATA (mybuf) = g_memdup (buf, len); | |
203 | GST_BUFFER_SIZE (mybuf) = len; | |
204 | GST_BUFFER_DATA (mybuf) = GST_BUFFER_MALLOCDATA (mybuf); | |
205 | if (GST_PAD_CAPS (basesrc->srcpad)) | |
206 | GST_BUFFER_CAPS (mybuf) = gst_caps_ref (GST_PAD_CAPS (basesrc->srcpad)); | |
207 | ||
208 | mybuf->from = nicesrc->from; | |
209 | mybuf->to = nicesrc->to; | |
210 | ||
211 | nicesrc->outbuf = GST_BUFFER_CAST (mybuf); | |
200 | nicesrc->flow_ret = gst_pad_alloc_buffer (basesrc->srcpad, nicesrc->offset, | |
201 | len, GST_PAD_CAPS (basesrc->srcpad), &nicesrc->outbuf); | |
202 | if (nicesrc->flow_ret == GST_FLOW_OK) { | |
203 | memcpy (nicesrc->outbuf->data, buf, len); | |
204 | nicesrc->outbuf->size = len; | |
205 | } | |
212 | 206 | |
213 | 207 | g_main_loop_quit (nicesrc->mainloop); |
214 | 208 | } |
220 | 214 | |
221 | 215 | g_main_loop_quit (nicesrc->mainloop); |
222 | 216 | |
223 | GST_OBJECT_LOCK (nicesrc); | |
224 | 217 | g_source_unref (nicesrc->idle_source); |
225 | 218 | nicesrc->idle_source = NULL; |
226 | GST_OBJECT_UNLOCK (nicesrc); | |
227 | 219 | |
228 | 220 | return FALSE; |
229 | 221 | } |
274 | 266 | GST_LOG_OBJECT (nicesrc, "create called"); |
275 | 267 | |
276 | 268 | nicesrc->outbuf = NULL; |
269 | nicesrc->offset = offset; | |
277 | 270 | |
278 | 271 | GST_OBJECT_LOCK (basesrc); |
279 | 272 | if (nicesrc->unlocked) { |
288 | 281 | GST_LOG_OBJECT (nicesrc, "Got buffer, pushing"); |
289 | 282 | |
290 | 283 | *buffer = nicesrc->outbuf; |
291 | GST_BUFFER_OFFSET (*buffer) = offset; | |
292 | ||
293 | return GST_FLOW_OK; | |
284 | return nicesrc->flow_ret; | |
294 | 285 | } else { |
295 | 286 | GST_LOG_OBJECT (nicesrc, "Got interrupting, returning wrong-state"); |
296 | 287 | return GST_FLOW_WRONG_STATE; |
297 | 288 | } |
289 | ||
298 | 290 | } |
299 | 291 | |
300 | 292 | static void |
301 | 293 | gst_nice_src_dispose (GObject *object) |
302 | 294 | { |
303 | 295 | GstNiceSrc *src = GST_NICE_SRC (object); |
304 | ||
305 | if (src->new_selected_pair_id) | |
306 | g_signal_handler_disconnect (src->agent, src->new_selected_pair_id); | |
307 | src->new_selected_pair_id = 0; | |
308 | 296 | |
309 | 297 | if (src->agent) |
310 | 298 | g_object_unref (src->agent); |
377 | 365 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
378 | 366 | break; |
379 | 367 | } |
380 | } | |
381 | ||
382 | static void | |
383 | nice_address_to_gst_net_address (NiceAddress *niceaddr, GstNetAddress *gstaddr) | |
384 | { | |
385 | switch (niceaddr->s.addr.sa_family) | |
386 | { | |
387 | case AF_INET: | |
388 | gst_netaddress_set_ip4_address (gstaddr, | |
389 | niceaddr->s.ip4.sin_addr.s_addr, | |
390 | niceaddr->s.ip4.sin_port); | |
391 | break; | |
392 | case AF_INET6: | |
393 | gst_netaddress_set_ip6_address (gstaddr, | |
394 | niceaddr->s.ip6.sin6_addr.s6_addr, | |
395 | niceaddr->s.ip6.sin6_port); | |
396 | break; | |
397 | default: | |
398 | break; | |
399 | } | |
400 | } | |
401 | ||
402 | static void | |
403 | new_selected_pair_cb (NiceAgent *agent, guint stream_id, guint component_id, | |
404 | gchar *local_cand, gchar *remote_cand, GstNiceSrc *src) | |
405 | { | |
406 | GST_OBJECT_LOCK (src); | |
407 | ||
408 | if (stream_id == src->stream_id && component_id == src->component_id) | |
409 | { | |
410 | GSList *local_candidates = nice_agent_get_local_candidates ( | |
411 | src->agent, stream_id, component_id); | |
412 | GSList *remote_candidates = nice_agent_get_remote_candidates ( | |
413 | src->agent, stream_id, component_id); | |
414 | GSList *item = NULL; | |
415 | ||
416 | for (item = local_candidates; item; item = g_slist_next (item)) | |
417 | { | |
418 | NiceCandidate *cand = item->data; | |
419 | if (!strcmp (local_cand, cand->foundation)) | |
420 | { | |
421 | nice_address_to_gst_net_address (&cand->addr, &src->to); | |
422 | break; | |
423 | } | |
424 | } | |
425 | ||
426 | for (item = remote_candidates; item; item = g_slist_next (item)) | |
427 | { | |
428 | NiceCandidate *cand = item->data; | |
429 | if (!strcmp (remote_cand, cand->foundation)) | |
430 | { | |
431 | nice_address_to_gst_net_address (&cand->addr, &src->from); | |
432 | break; | |
433 | } | |
434 | } | |
435 | ||
436 | g_slist_foreach (local_candidates, (GFunc) nice_candidate_free, NULL); | |
437 | g_slist_free (local_candidates); | |
438 | g_slist_foreach (remote_candidates, (GFunc) nice_candidate_free, NULL); | |
439 | g_slist_free (remote_candidates); | |
440 | } | |
441 | ||
442 | GST_OBJECT_UNLOCK (src); | |
443 | 368 | } |
444 | 369 | |
445 | 370 | static GstStateChangeReturn |
460 | 385 | } |
461 | 386 | else |
462 | 387 | { |
463 | GST_OBJECT_LOCK (src); | |
464 | 388 | nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, |
465 | 389 | g_main_loop_get_context (src->mainloop), |
466 | 390 | gst_nice_src_read_callback, (gpointer) src); |
467 | ||
468 | if (!src->new_selected_pair_id) | |
469 | src->new_selected_pair_id = g_signal_connect (src->agent, | |
470 | "new-selected-pair", G_CALLBACK (new_selected_pair_cb), src); | |
471 | GST_OBJECT_UNLOCK (src); | |
472 | 391 | } |
473 | 392 | break; |
474 | 393 | case GST_STATE_CHANGE_READY_TO_NULL: |
475 | GST_OBJECT_LOCK (src); | |
476 | 394 | nice_agent_attach_recv (src->agent, src->stream_id, src->component_id, |
477 | 395 | g_main_loop_get_context (src->mainloop), NULL, NULL); |
478 | if (src->new_selected_pair_id) | |
479 | g_signal_handler_disconnect (src->agent, src->new_selected_pair_id); | |
480 | src->new_selected_pair_id = 0; | |
481 | GST_OBJECT_UNLOCK (src); | |
482 | 396 | break; |
483 | 397 | default: |
484 | 398 | break; |
39 | 39 | |
40 | 40 | #include <gst/gst.h> |
41 | 41 | #include <gst/base/gstbasesrc.h> |
42 | #include <gst/netbuffer/gstnetbuffer.h> | |
43 | 42 | |
44 | 43 | #include <nice/nice.h> |
45 | 44 | |
62 | 61 | { |
63 | 62 | GstBaseSrc parent; |
64 | 63 | GstPad *srcpad; |
65 | GMainLoop *mainloop; | |
66 | ||
67 | /* Protected by the object lock */ | |
68 | gboolean unlocked; | |
69 | GSource *idle_source; | |
70 | 64 | NiceAgent *agent; |
71 | 65 | guint stream_id; |
72 | 66 | guint component_id; |
73 | ||
74 | /* Protected by the stream lock */ | |
67 | GMainLoop *mainloop; | |
68 | guint64 offset; | |
69 | GstFlowReturn flow_ret; | |
75 | 70 | GstBuffer *outbuf; |
76 | ||
77 | /* Protected by the object lock */ | |
78 | gulong new_selected_pair_id; | |
79 | GstNetAddress from; | |
80 | GstNetAddress to; | |
71 | gboolean unlocked; | |
72 | GSource *idle_source; | |
81 | 73 | }; |
82 | 74 | |
83 | 75 | typedef struct _GstNiceSrcClass GstNiceSrcClass; |
0 | 0 | # Generated from ltmain.m4sh. |
1 | 1 | |
2 | # ltmain.sh (GNU libtool) 2.2.4 | |
2 | # ltmain.sh (GNU libtool) 2.2.6 | |
3 | 3 | # Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 |
4 | 4 | |
5 | 5 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. |
64 | 64 | # compiler: $LTCC |
65 | 65 | # compiler flags: $LTCFLAGS |
66 | 66 | # linker: $LD (gnu? $with_gnu_ld) |
67 | # $progname: (GNU libtool) 2.2.4 Debian-2.2.4-0ubuntu4 | |
67 | # $progname: (GNU libtool) 2.2.6 Debian-2.2.6a-1 | |
68 | 68 | # automake: $automake_version |
69 | 69 | # autoconf: $autoconf_version |
70 | 70 | # |
72 | 72 | |
73 | 73 | PROGRAM=ltmain.sh |
74 | 74 | PACKAGE=libtool |
75 | VERSION="2.2.4 Debian-2.2.4-0ubuntu4" | |
75 | VERSION="2.2.6 Debian-2.2.6a-1" | |
76 | 76 | TIMESTAMP="" |
77 | package_revision=1.2976 | |
77 | package_revision=1.3012 | |
78 | 78 | |
79 | 79 | # Be Bourne compatible |
80 | 80 | if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then |
804 | 804 | |
805 | 805 | |
806 | 806 | case $host in |
807 | *cygwin* | *mingw* | *pw32*) | |
807 | *cygwin* | *mingw* | *pw32* | *cegcc*) | |
808 | 808 | # don't eliminate duplications in $postdeps and $predeps |
809 | 809 | opt_duplicate_compiler_generated_deps=: |
810 | 810 | ;; |
892 | 892 | # determined imposters. |
893 | 893 | func_lalib_p () |
894 | 894 | { |
895 | $SED -e 4q "$1" 2>/dev/null \ | |
896 | | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 | |
895 | test -f "$1" && | |
896 | $SED -e 4q "$1" 2>/dev/null \ | |
897 | | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 | |
897 | 898 | } |
898 | 899 | |
899 | 900 | # func_lalib_unsafe_p file |
906 | 907 | func_lalib_unsafe_p () |
907 | 908 | { |
908 | 909 | lalib_p=no |
909 | if test -r "$1" && exec 5<&0 <"$1"; then | |
910 | if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then | |
910 | 911 | for lalib_p_l in 1 2 3 4 |
911 | 912 | do |
912 | 913 | read lalib_p_line |
1274 | 1275 | |
1275 | 1276 | # On Cygwin there's no "real" PIC flag so we must build both object types |
1276 | 1277 | case $host_os in |
1277 | cygwin* | mingw* | pw32* | os2*) | |
1278 | cygwin* | mingw* | pw32* | os2* | cegcc*) | |
1278 | 1279 | pic_mode=default |
1279 | 1280 | ;; |
1280 | 1281 | esac |
2045 | 2046 | 'exit $?' |
2046 | 2047 | tstripme="$stripme" |
2047 | 2048 | case $host_os in |
2048 | cygwin* | mingw* | pw32*) | |
2049 | cygwin* | mingw* | pw32* | cegcc*) | |
2049 | 2050 | case $realname in |
2050 | 2051 | *.dll.a) |
2051 | 2052 | tstripme="" |
2151 | 2152 | |
2152 | 2153 | # Do a test to see if this is really a libtool program. |
2153 | 2154 | case $host in |
2154 | *cygwin*|*mingw*) | |
2155 | *cygwin* | *mingw*) | |
2155 | 2156 | if func_ltwrapper_executable_p "$file"; then |
2156 | 2157 | func_ltwrapper_scriptname "$file" |
2157 | 2158 | wrapper=$func_ltwrapper_scriptname_result |
2357 | 2358 | $RM $export_symbols |
2358 | 2359 | eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' |
2359 | 2360 | case $host in |
2360 | *cygwin* | *mingw* ) | |
2361 | *cygwin* | *mingw* | *cegcc* ) | |
2361 | 2362 | eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' |
2362 | 2363 | eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' |
2363 | 2364 | ;; |
2369 | 2370 | eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' |
2370 | 2371 | eval '$MV "$nlist"T "$nlist"' |
2371 | 2372 | case $host in |
2372 | *cygwin | *mingw* ) | |
2373 | *cygwin | *mingw* | *cegcc* ) | |
2373 | 2374 | eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' |
2374 | 2375 | eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' |
2375 | 2376 | ;; |
2425 | 2426 | } lt_dlsymlist; |
2426 | 2427 | " |
2427 | 2428 | case $host in |
2428 | *cygwin* | *mingw* ) | |
2429 | *cygwin* | *mingw* | *cegcc* ) | |
2429 | 2430 | $ECHO >> "$output_objdir/$my_dlsyms" "\ |
2430 | 2431 | /* DATA imports from DLLs on WIN32 con't be const, because |
2431 | 2432 | runtime relocations are performed -- see ld's documentation |
2511 | 2512 | # Transform the symbol file into the correct name. |
2512 | 2513 | symfileobj="$output_objdir/${my_outputname}S.$objext" |
2513 | 2514 | case $host in |
2514 | *cygwin* | *mingw* ) | |
2515 | *cygwin* | *mingw* | *cegcc* ) | |
2515 | 2516 | if test -f "$output_objdir/$my_outputname.def"; then |
2516 | 2517 | compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` |
2517 | 2518 | finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` |
2690 | 2691 | |
2691 | 2692 | |
2692 | 2693 | |
2693 | # func_emit_wrapper arg | |
2694 | # func_emit_wrapper_part1 [arg=no] | |
2694 | 2695 | # |
2695 | # emit a libtool wrapper script on stdout | |
2696 | # don't directly open a file because we may want to | |
2697 | # incorporate the script contents within a cygwin/mingw | |
2698 | # wrapper executable. Must ONLY be called from within | |
2699 | # func_mode_link because it depends on a number of variable | |
2700 | # set therein. | |
2701 | # | |
2702 | # arg is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR | |
2703 | # variable will take. If 'yes', then the emitted script | |
2704 | # will assume that the directory in which it is stored is | |
2705 | # the '.lib' directory. This is a cygwin/mingw-specific | |
2706 | # behavior. | |
2707 | func_emit_wrapper () | |
2696 | # Emit the first part of a libtool wrapper script on stdout. | |
2697 | # For more information, see the description associated with | |
2698 | # func_emit_wrapper(), below. | |
2699 | func_emit_wrapper_part1 () | |
2708 | 2700 | { |
2709 | func_emit_wrapper_arg1=no | |
2701 | func_emit_wrapper_part1_arg1=no | |
2710 | 2702 | if test -n "$1" ; then |
2711 | func_emit_wrapper_arg1=$1 | |
2703 | func_emit_wrapper_part1_arg1=$1 | |
2712 | 2704 | fi |
2713 | 2705 | |
2714 | 2706 | $ECHO "\ |
2793 | 2785 | file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` |
2794 | 2786 | file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` |
2795 | 2787 | done |
2788 | " | |
2789 | } | |
2790 | # end: func_emit_wrapper_part1 | |
2791 | ||
2792 | # func_emit_wrapper_part2 [arg=no] | |
2793 | # | |
2794 | # Emit the second part of a libtool wrapper script on stdout. | |
2795 | # For more information, see the description associated with | |
2796 | # func_emit_wrapper(), below. | |
2797 | func_emit_wrapper_part2 () | |
2798 | { | |
2799 | func_emit_wrapper_part2_arg1=no | |
2800 | if test -n "$1" ; then | |
2801 | func_emit_wrapper_part2_arg1=$1 | |
2802 | fi | |
2803 | ||
2804 | $ECHO "\ | |
2796 | 2805 | |
2797 | 2806 | # Usually 'no', except on cygwin/mingw when embedded into |
2798 | 2807 | # the cwrapper. |
2799 | WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 | |
2808 | WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 | |
2800 | 2809 | if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then |
2801 | 2810 | # special case for '.' |
2802 | 2811 | if test \"\$thisdir\" = \".\"; then |
2887 | 2896 | " |
2888 | 2897 | case $host in |
2889 | 2898 | # Backslashes separate directories on plain windows |
2890 | *-*-mingw | *-*-os2*) | |
2899 | *-*-mingw | *-*-os2* | *-cegcc*) | |
2891 | 2900 | $ECHO "\ |
2892 | 2901 | exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} |
2893 | 2902 | " |
2913 | 2922 | fi\ |
2914 | 2923 | " |
2915 | 2924 | } |
2916 | # end: func_emit_wrapper | |
2925 | # end: func_emit_wrapper_part2 | |
2926 | ||
2927 | ||
2928 | # func_emit_wrapper [arg=no] | |
2929 | # | |
2930 | # Emit a libtool wrapper script on stdout. | |
2931 | # Don't directly open a file because we may want to | |
2932 | # incorporate the script contents within a cygwin/mingw | |
2933 | # wrapper executable. Must ONLY be called from within | |
2934 | # func_mode_link because it depends on a number of variables | |
2935 | # set therein. | |
2936 | # | |
2937 | # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR | |
2938 | # variable will take. If 'yes', then the emitted script | |
2939 | # will assume that the directory in which it is stored is | |
2940 | # the $objdir directory. This is a cygwin/mingw-specific | |
2941 | # behavior. | |
2942 | func_emit_wrapper () | |
2943 | { | |
2944 | func_emit_wrapper_arg1=no | |
2945 | if test -n "$1" ; then | |
2946 | func_emit_wrapper_arg1=$1 | |
2947 | fi | |
2948 | ||
2949 | # split this up so that func_emit_cwrapperexe_src | |
2950 | # can call each part independently. | |
2951 | func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" | |
2952 | func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" | |
2953 | } | |
2954 | ||
2955 | ||
2956 | # func_to_host_path arg | |
2957 | # | |
2958 | # Convert paths to host format when used with build tools. | |
2959 | # Intended for use with "native" mingw (where libtool itself | |
2960 | # is running under the msys shell), or in the following cross- | |
2961 | # build environments: | |
2962 | # $build $host | |
2963 | # mingw (msys) mingw [e.g. native] | |
2964 | # cygwin mingw | |
2965 | # *nix + wine mingw | |
2966 | # where wine is equipped with the `winepath' executable. | |
2967 | # In the native mingw case, the (msys) shell automatically | |
2968 | # converts paths for any non-msys applications it launches, | |
2969 | # but that facility isn't available from inside the cwrapper. | |
2970 | # Similar accommodations are necessary for $host mingw and | |
2971 | # $build cygwin. Calling this function does no harm for other | |
2972 | # $host/$build combinations not listed above. | |
2973 | # | |
2974 | # ARG is the path (on $build) that should be converted to | |
2975 | # the proper representation for $host. The result is stored | |
2976 | # in $func_to_host_path_result. | |
2977 | func_to_host_path () | |
2978 | { | |
2979 | func_to_host_path_result="$1" | |
2980 | if test -n "$1" ; then | |
2981 | case $host in | |
2982 | *mingw* ) | |
2983 | lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' | |
2984 | case $build in | |
2985 | *mingw* ) # actually, msys | |
2986 | # awkward: cmd appends spaces to result | |
2987 | lt_sed_strip_trailing_spaces="s/[ ]*\$//" | |
2988 | func_to_host_path_tmp1=`( cmd //c echo "$1" |\ | |
2989 | $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` | |
2990 | func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ | |
2991 | $SED -e "$lt_sed_naive_backslashify"` | |
2992 | ;; | |
2993 | *cygwin* ) | |
2994 | func_to_host_path_tmp1=`cygpath -w "$1"` | |
2995 | func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ | |
2996 | $SED -e "$lt_sed_naive_backslashify"` | |
2997 | ;; | |
2998 | * ) | |
2999 | # Unfortunately, winepath does not exit with a non-zero | |
3000 | # error code, so we are forced to check the contents of | |
3001 | # stdout. On the other hand, if the command is not | |
3002 | # found, the shell will set an exit code of 127 and print | |
3003 | # *an error message* to stdout. So we must check for both | |
3004 | # error code of zero AND non-empty stdout, which explains | |
3005 | # the odd construction: | |
3006 | func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` | |
3007 | if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then | |
3008 | func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ | |
3009 | $SED -e "$lt_sed_naive_backslashify"` | |
3010 | else | |
3011 | # Allow warning below. | |
3012 | func_to_host_path_result="" | |
3013 | fi | |
3014 | ;; | |
3015 | esac | |
3016 | if test -z "$func_to_host_path_result" ; then | |
3017 | func_error "Could not determine host path corresponding to" | |
3018 | func_error " '$1'" | |
3019 | func_error "Continuing, but uninstalled executables may not work." | |
3020 | # Fallback: | |
3021 | func_to_host_path_result="$1" | |
3022 | fi | |
3023 | ;; | |
3024 | esac | |
3025 | fi | |
3026 | } | |
3027 | # end: func_to_host_path | |
3028 | ||
3029 | # func_to_host_pathlist arg | |
3030 | # | |
3031 | # Convert pathlists to host format when used with build tools. | |
3032 | # See func_to_host_path(), above. This function supports the | |
3033 | # following $build/$host combinations (but does no harm for | |
3034 | # combinations not listed here): | |
3035 | # $build $host | |
3036 | # mingw (msys) mingw [e.g. native] | |
3037 | # cygwin mingw | |
3038 | # *nix + wine mingw | |
3039 | # | |
3040 | # Path separators are also converted from $build format to | |
3041 | # $host format. If ARG begins or ends with a path separator | |
3042 | # character, it is preserved (but converted to $host format) | |
3043 | # on output. | |
3044 | # | |
3045 | # ARG is a pathlist (on $build) that should be converted to | |
3046 | # the proper representation on $host. The result is stored | |
3047 | # in $func_to_host_pathlist_result. | |
3048 | func_to_host_pathlist () | |
3049 | { | |
3050 | func_to_host_pathlist_result="$1" | |
3051 | if test -n "$1" ; then | |
3052 | case $host in | |
3053 | *mingw* ) | |
3054 | lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' | |
3055 | # Remove leading and trailing path separator characters from | |
3056 | # ARG. msys behavior is inconsistent here, cygpath turns them | |
3057 | # into '.;' and ';.', and winepath ignores them completely. | |
3058 | func_to_host_pathlist_tmp2="$1" | |
3059 | # Once set for this call, this variable should not be | |
3060 | # reassigned. It is used in tha fallback case. | |
3061 | func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ | |
3062 | $SED -e 's|^:*||' -e 's|:*$||'` | |
3063 | case $build in | |
3064 | *mingw* ) # Actually, msys. | |
3065 | # Awkward: cmd appends spaces to result. | |
3066 | lt_sed_strip_trailing_spaces="s/[ ]*\$//" | |
3067 | func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ | |
3068 | $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` | |
3069 | func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ | |
3070 | $SED -e "$lt_sed_naive_backslashify"` | |
3071 | ;; | |
3072 | *cygwin* ) | |
3073 | func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` | |
3074 | func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ | |
3075 | $SED -e "$lt_sed_naive_backslashify"` | |
3076 | ;; | |
3077 | * ) | |
3078 | # unfortunately, winepath doesn't convert pathlists | |
3079 | func_to_host_pathlist_result="" | |
3080 | func_to_host_pathlist_oldIFS=$IFS | |
3081 | IFS=: | |
3082 | for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do | |
3083 | IFS=$func_to_host_pathlist_oldIFS | |
3084 | if test -n "$func_to_host_pathlist_f" ; then | |
3085 | func_to_host_path "$func_to_host_pathlist_f" | |
3086 | if test -n "$func_to_host_path_result" ; then | |
3087 | if test -z "$func_to_host_pathlist_result" ; then | |
3088 | func_to_host_pathlist_result="$func_to_host_path_result" | |
3089 | else | |
3090 | func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" | |
3091 | fi | |
3092 | fi | |
3093 | fi | |
3094 | IFS=: | |
3095 | done | |
3096 | IFS=$func_to_host_pathlist_oldIFS | |
3097 | ;; | |
3098 | esac | |
3099 | if test -z "$func_to_host_pathlist_result" ; then | |
3100 | func_error "Could not determine the host path(s) corresponding to" | |
3101 | func_error " '$1'" | |
3102 | func_error "Continuing, but uninstalled executables may not work." | |
3103 | # Fallback. This may break if $1 contains DOS-style drive | |
3104 | # specifications. The fix is not to complicate the expression | |
3105 | # below, but for the user to provide a working wine installation | |
3106 | # with winepath so that path translation in the cross-to-mingw | |
3107 | # case works properly. | |
3108 | lt_replace_pathsep_nix_to_dos="s|:|;|g" | |
3109 | func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ | |
3110 | $SED -e "$lt_replace_pathsep_nix_to_dos"` | |
3111 | fi | |
3112 | # Now, add the leading and trailing path separators back | |
3113 | case "$1" in | |
3114 | :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" | |
3115 | ;; | |
3116 | esac | |
3117 | case "$1" in | |
3118 | *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" | |
3119 | ;; | |
3120 | esac | |
3121 | ;; | |
3122 | esac | |
3123 | fi | |
3124 | } | |
3125 | # end: func_to_host_pathlist | |
2917 | 3126 | |
2918 | 3127 | # func_emit_cwrapperexe_src |
2919 | 3128 | # emit the source code for a wrapper executable on stdout |
2950 | 3159 | # include <stdint.h> |
2951 | 3160 | # ifdef __CYGWIN__ |
2952 | 3161 | # include <io.h> |
3162 | # define HAVE_SETENV | |
3163 | # ifdef __STRICT_ANSI__ | |
3164 | char *realpath (const char *, char *); | |
3165 | int putenv (char *); | |
3166 | int setenv (const char *, const char *, int); | |
3167 | # endif | |
2953 | 3168 | # endif |
2954 | 3169 | #endif |
2955 | 3170 | #include <malloc.h> |
3056 | 3271 | int check_executable (const char *path); |
3057 | 3272 | char *strendzap (char *str, const char *pat); |
3058 | 3273 | void lt_fatal (const char *message, ...); |
3059 | ||
3060 | static const char *script_text = | |
3274 | void lt_setenv (const char *name, const char *value); | |
3275 | char *lt_extend_str (const char *orig_value, const char *add, int to_end); | |
3276 | void lt_opt_process_env_set (const char *arg); | |
3277 | void lt_opt_process_env_prepend (const char *arg); | |
3278 | void lt_opt_process_env_append (const char *arg); | |
3279 | int lt_split_name_value (const char *arg, char** name, char** value); | |
3280 | void lt_update_exe_path (const char *name, const char *value); | |
3281 | void lt_update_lib_path (const char *name, const char *value); | |
3282 | ||
3283 | static const char *script_text_part1 = | |
3061 | 3284 | EOF |
3062 | 3285 | |
3063 | func_emit_wrapper yes | | |
3286 | func_emit_wrapper_part1 yes | | |
3064 | 3287 | $SED -e 's/\([\\"]\)/\\\1/g' \ |
3065 | 3288 | -e 's/^/ "/' -e 's/$/\\n"/' |
3066 | 3289 | echo ";" |
3290 | cat <<EOF | |
3291 | ||
3292 | static const char *script_text_part2 = | |
3293 | EOF | |
3294 | func_emit_wrapper_part2 yes | | |
3295 | $SED -e 's/\([\\"]\)/\\\1/g' \ | |
3296 | -e 's/^/ "/' -e 's/$/\\n"/' | |
3297 | echo ";" | |
3067 | 3298 | |
3068 | 3299 | cat <<EOF |
3069 | 3300 | const char * MAGIC_EXE = "$magic_exe"; |
3301 | const char * LIB_PATH_VARNAME = "$shlibpath_var"; | |
3302 | EOF | |
3303 | ||
3304 | if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then | |
3305 | func_to_host_pathlist "$temp_rpath" | |
3306 | cat <<EOF | |
3307 | const char * LIB_PATH_VALUE = "$func_to_host_pathlist_result"; | |
3308 | EOF | |
3309 | else | |
3310 | cat <<"EOF" | |
3311 | const char * LIB_PATH_VALUE = ""; | |
3312 | EOF | |
3313 | fi | |
3314 | ||
3315 | if test -n "$dllsearchpath"; then | |
3316 | func_to_host_pathlist "$dllsearchpath:" | |
3317 | cat <<EOF | |
3318 | const char * EXE_PATH_VARNAME = "PATH"; | |
3319 | const char * EXE_PATH_VALUE = "$func_to_host_pathlist_result"; | |
3320 | EOF | |
3321 | else | |
3322 | cat <<"EOF" | |
3323 | const char * EXE_PATH_VARNAME = ""; | |
3324 | const char * EXE_PATH_VALUE = ""; | |
3325 | EOF | |
3326 | fi | |
3327 | ||
3328 | if test "$fast_install" = yes; then | |
3329 | cat <<EOF | |
3330 | const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ | |
3331 | EOF | |
3332 | else | |
3333 | cat <<EOF | |
3334 | const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ | |
3335 | EOF | |
3336 | fi | |
3337 | ||
3338 | ||
3339 | cat <<"EOF" | |
3340 | ||
3341 | #define LTWRAPPER_OPTION_PREFIX "--lt-" | |
3342 | #define LTWRAPPER_OPTION_PREFIX_LENGTH 5 | |
3343 | ||
3344 | static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH; | |
3345 | static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; | |
3346 | ||
3347 | static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; | |
3348 | ||
3349 | static const size_t env_set_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 7; | |
3350 | static const char *env_set_opt = LTWRAPPER_OPTION_PREFIX "env-set"; | |
3351 | /* argument is putenv-style "foo=bar", value of foo is set to bar */ | |
3352 | ||
3353 | static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11; | |
3354 | static const char *env_prepend_opt = LTWRAPPER_OPTION_PREFIX "env-prepend"; | |
3355 | /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */ | |
3356 | ||
3357 | static const size_t env_append_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 10; | |
3358 | static const char *env_append_opt = LTWRAPPER_OPTION_PREFIX "env-append"; | |
3359 | /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */ | |
3070 | 3360 | |
3071 | 3361 | int |
3072 | 3362 | main (int argc, char *argv[]) |
3073 | 3363 | { |
3074 | 3364 | char **newargz; |
3365 | int newargc; | |
3075 | 3366 | char *tmp_pathspec; |
3076 | 3367 | char *actual_cwrapper_path; |
3077 | char *shwrapper_name; | |
3368 | char *actual_cwrapper_name; | |
3369 | char *target_name; | |
3370 | char *lt_argv_zero; | |
3078 | 3371 | intptr_t rval = 127; |
3079 | FILE *shwrapper; | |
3080 | ||
3081 | const char *dumpscript_opt = "--lt-dump-script"; | |
3372 | ||
3082 | 3373 | int i; |
3083 | 3374 | |
3084 | 3375 | program_name = (char *) xstrdup (base_name (argv[0])); |
3098 | 3389 | ;; |
3099 | 3390 | esac |
3100 | 3391 | |
3101 | cat <<EOF | |
3102 | printf ("%s", script_text); | |
3392 | cat <<"EOF" | |
3393 | printf ("%s", script_text_part1); | |
3394 | printf ("%s", script_text_part2); | |
3103 | 3395 | return 0; |
3104 | 3396 | } |
3105 | 3397 | } |
3106 | 3398 | |
3107 | newargz = XMALLOC (char *, argc + 2); | |
3108 | EOF | |
3109 | ||
3110 | if test -n "$TARGETSHELL" ; then | |
3111 | # no path translation at all | |
3112 | lt_newargv0=$TARGETSHELL | |
3113 | else | |
3114 | case "$host" in | |
3115 | *mingw* ) | |
3116 | # awkward: cmd appends spaces to result | |
3117 | lt_sed_strip_trailing_spaces="s/[ ]*\$//" | |
3118 | lt_newargv0=`( cmd //c echo $SHELL | $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo $SHELL` | |
3119 | case $lt_newargv0 in | |
3120 | *.exe | *.EXE) ;; | |
3121 | *) lt_newargv0=$lt_newargv0.exe ;; | |
3122 | esac | |
3123 | ;; | |
3124 | * ) lt_newargv0=$SHELL ;; | |
3125 | esac | |
3126 | fi | |
3127 | ||
3128 | cat <<EOF | |
3129 | newargz[0] = (char *) xstrdup ("$lt_newargv0"); | |
3130 | EOF | |
3131 | ||
3132 | cat <<"EOF" | |
3399 | newargz = XMALLOC (char *, argc + 1); | |
3133 | 3400 | tmp_pathspec = find_executable (argv[0]); |
3134 | 3401 | if (tmp_pathspec == NULL) |
3135 | 3402 | lt_fatal ("Couldn't find %s", argv[0]); |
3141 | 3408 | actual_cwrapper_path)); |
3142 | 3409 | XFREE (tmp_pathspec); |
3143 | 3410 | |
3144 | shwrapper_name = (char *) xstrdup (base_name (actual_cwrapper_path)); | |
3145 | strendzap (actual_cwrapper_path, shwrapper_name); | |
3146 | ||
3147 | /* shwrapper_name transforms */ | |
3148 | strendzap (shwrapper_name, ".exe"); | |
3149 | tmp_pathspec = XMALLOC (char, (strlen (shwrapper_name) + | |
3150 | strlen ("_ltshwrapperTMP") + 1)); | |
3151 | strcpy (tmp_pathspec, shwrapper_name); | |
3152 | strcat (tmp_pathspec, "_ltshwrapperTMP"); | |
3153 | XFREE (shwrapper_name); | |
3154 | shwrapper_name = tmp_pathspec; | |
3411 | actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path)); | |
3412 | strendzap (actual_cwrapper_path, actual_cwrapper_name); | |
3413 | ||
3414 | /* wrapper name transforms */ | |
3415 | strendzap (actual_cwrapper_name, ".exe"); | |
3416 | tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); | |
3417 | XFREE (actual_cwrapper_name); | |
3418 | actual_cwrapper_name = tmp_pathspec; | |
3155 | 3419 | tmp_pathspec = 0; |
3156 | LTWRAPPER_DEBUGPRINTF (("(main) libtool shell wrapper name: %s\n", | |
3157 | shwrapper_name)); | |
3420 | ||
3421 | /* target_name transforms -- use actual target program name; might have lt- prefix */ | |
3422 | target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); | |
3423 | strendzap (target_name, ".exe"); | |
3424 | tmp_pathspec = lt_extend_str (target_name, ".exe", 1); | |
3425 | XFREE (target_name); | |
3426 | target_name = tmp_pathspec; | |
3427 | tmp_pathspec = 0; | |
3428 | ||
3429 | LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n", | |
3430 | target_name)); | |
3158 | 3431 | EOF |
3159 | 3432 | |
3160 | 3433 | cat <<EOF |
3161 | newargz[1] = | |
3434 | newargz[0] = | |
3162 | 3435 | XMALLOC (char, (strlen (actual_cwrapper_path) + |
3163 | strlen ("$objdir") + 1 + strlen (shwrapper_name) + 1)); | |
3164 | strcpy (newargz[1], actual_cwrapper_path); | |
3165 | strcat (newargz[1], "$objdir"); | |
3166 | strcat (newargz[1], "/"); | |
3167 | strcat (newargz[1], shwrapper_name); | |
3436 | strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); | |
3437 | strcpy (newargz[0], actual_cwrapper_path); | |
3438 | strcat (newargz[0], "$objdir"); | |
3439 | strcat (newargz[0], "/"); | |
3168 | 3440 | EOF |
3169 | 3441 | |
3442 | cat <<"EOF" | |
3443 | /* stop here, and copy so we don't have to do this twice */ | |
3444 | tmp_pathspec = xstrdup (newargz[0]); | |
3445 | ||
3446 | /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ | |
3447 | strcat (newargz[0], actual_cwrapper_name); | |
3448 | ||
3449 | /* DO want the lt- prefix here if it exists, so use target_name */ | |
3450 | lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); | |
3451 | XFREE (tmp_pathspec); | |
3452 | tmp_pathspec = NULL; | |
3453 | EOF | |
3170 | 3454 | |
3171 | 3455 | case $host_os in |
3172 | 3456 | mingw*) |
3173 | 3457 | cat <<"EOF" |
3174 | 3458 | { |
3175 | 3459 | char* p; |
3176 | while ((p = strchr (newargz[1], '\\')) != NULL) | |
3460 | while ((p = strchr (newargz[0], '\\')) != NULL) | |
3461 | { | |
3462 | *p = '/'; | |
3463 | } | |
3464 | while ((p = strchr (lt_argv_zero, '\\')) != NULL) | |
3177 | 3465 | { |
3178 | 3466 | *p = '/'; |
3179 | 3467 | } |
3183 | 3471 | esac |
3184 | 3472 | |
3185 | 3473 | cat <<"EOF" |
3186 | XFREE (shwrapper_name); | |
3474 | XFREE (target_name); | |
3187 | 3475 | XFREE (actual_cwrapper_path); |
3188 | ||
3189 | /* always write in binary mode */ | |
3190 | if ((shwrapper = fopen (newargz[1], FOPEN_WB)) == 0) | |
3476 | XFREE (actual_cwrapper_name); | |
3477 | ||
3478 | lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ | |
3479 | lt_setenv ("DUALCASE", "1"); /* for MSK sh */ | |
3480 | lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); | |
3481 | lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); | |
3482 | ||
3483 | newargc=0; | |
3484 | for (i = 1; i < argc; i++) | |
3191 | 3485 | { |
3192 | lt_fatal ("Could not open %s for writing", newargz[1]); | |
3486 | if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0) | |
3487 | { | |
3488 | if (argv[i][env_set_opt_len] == '=') | |
3489 | { | |
3490 | const char *p = argv[i] + env_set_opt_len + 1; | |
3491 | lt_opt_process_env_set (p); | |
3492 | } | |
3493 | else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc) | |
3494 | { | |
3495 | lt_opt_process_env_set (argv[++i]); /* don't copy */ | |
3496 | } | |
3497 | else | |
3498 | lt_fatal ("%s missing required argument", env_set_opt); | |
3499 | continue; | |
3500 | } | |
3501 | if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0) | |
3502 | { | |
3503 | if (argv[i][env_prepend_opt_len] == '=') | |
3504 | { | |
3505 | const char *p = argv[i] + env_prepend_opt_len + 1; | |
3506 | lt_opt_process_env_prepend (p); | |
3507 | } | |
3508 | else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc) | |
3509 | { | |
3510 | lt_opt_process_env_prepend (argv[++i]); /* don't copy */ | |
3511 | } | |
3512 | else | |
3513 | lt_fatal ("%s missing required argument", env_prepend_opt); | |
3514 | continue; | |
3515 | } | |
3516 | if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0) | |
3517 | { | |
3518 | if (argv[i][env_append_opt_len] == '=') | |
3519 | { | |
3520 | const char *p = argv[i] + env_append_opt_len + 1; | |
3521 | lt_opt_process_env_append (p); | |
3522 | } | |
3523 | else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc) | |
3524 | { | |
3525 | lt_opt_process_env_append (argv[++i]); /* don't copy */ | |
3526 | } | |
3527 | else | |
3528 | lt_fatal ("%s missing required argument", env_append_opt); | |
3529 | continue; | |
3530 | } | |
3531 | if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0) | |
3532 | { | |
3533 | /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX | |
3534 | namespace, but it is not one of the ones we know about and | |
3535 | have already dealt with, above (inluding dump-script), then | |
3536 | report an error. Otherwise, targets might begin to believe | |
3537 | they are allowed to use options in the LTWRAPPER_OPTION_PREFIX | |
3538 | namespace. The first time any user complains about this, we'll | |
3539 | need to make LTWRAPPER_OPTION_PREFIX a configure-time option | |
3540 | or a configure.ac-settable value. | |
3541 | */ | |
3542 | lt_fatal ("Unrecognized option in %s namespace: '%s'", | |
3543 | ltwrapper_option_prefix, argv[i]); | |
3544 | } | |
3545 | /* otherwise ... */ | |
3546 | newargz[++newargc] = xstrdup (argv[i]); | |
3193 | 3547 | } |
3194 | fprintf (shwrapper, "%s", script_text); | |
3195 | fclose (shwrapper); | |
3196 | ||
3197 | make_executable (newargz[1]); | |
3198 | ||
3199 | for (i = 1; i < argc; i++) | |
3200 | newargz[i + 1] = xstrdup (argv[i]); | |
3201 | newargz[argc + 1] = NULL; | |
3202 | ||
3203 | for (i = 0; i < argc + 1; i++) | |
3548 | newargz[++newargc] = NULL; | |
3549 | ||
3550 | LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>"))); | |
3551 | for (i = 0; i < newargc; i++) | |
3204 | 3552 | { |
3205 | LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, newargz[i])); | |
3553 | LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>"))); | |
3206 | 3554 | } |
3207 | 3555 | |
3208 | 3556 | EOF |
3209 | 3557 | |
3210 | 3558 | case $host_os in |
3211 | 3559 | mingw*) |
3212 | cat <<EOF | |
3560 | cat <<"EOF" | |
3213 | 3561 | /* execv doesn't actually work on mingw as expected on unix */ |
3214 | rval = _spawnv (_P_WAIT, "$lt_newargv0", (const char * const *) newargz); | |
3562 | rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); | |
3215 | 3563 | if (rval == -1) |
3216 | 3564 | { |
3217 | 3565 | /* failed to start process */ |
3218 | LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"$lt_newargv0\": errno = %d\n", errno)); | |
3566 | LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); | |
3219 | 3567 | return 127; |
3220 | 3568 | } |
3221 | 3569 | return rval; |
3222 | } | |
3223 | 3570 | EOF |
3224 | 3571 | ;; |
3225 | 3572 | *) |
3226 | cat <<EOF | |
3227 | execv ("$lt_newargv0", newargz); | |
3573 | cat <<"EOF" | |
3574 | execv (lt_argv_zero, newargz); | |
3228 | 3575 | return rval; /* =127, but avoids unused variable warning */ |
3229 | } | |
3230 | 3576 | EOF |
3231 | 3577 | ;; |
3232 | 3578 | esac |
3233 | 3579 | |
3234 | 3580 | cat <<"EOF" |
3581 | } | |
3235 | 3582 | |
3236 | 3583 | void * |
3237 | 3584 | xmalloc (size_t num) |
3505 | 3852 | lt_error_core (EXIT_FAILURE, "FATAL", message, ap); |
3506 | 3853 | va_end (ap); |
3507 | 3854 | } |
3855 | ||
3856 | void | |
3857 | lt_setenv (const char *name, const char *value) | |
3858 | { | |
3859 | LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", | |
3860 | (name ? name : "<NULL>"), | |
3861 | (value ? value : "<NULL>"))); | |
3862 | { | |
3863 | #ifdef HAVE_SETENV | |
3864 | /* always make a copy, for consistency with !HAVE_SETENV */ | |
3865 | char *str = xstrdup (value); | |
3866 | setenv (name, str, 1); | |
3867 | #else | |
3868 | int len = strlen (name) + 1 + strlen (value) + 1; | |
3869 | char *str = XMALLOC (char, len); | |
3870 | sprintf (str, "%s=%s", name, value); | |
3871 | if (putenv (str) != EXIT_SUCCESS) | |
3872 | { | |
3873 | XFREE (str); | |
3874 | } | |
3875 | #endif | |
3876 | } | |
3877 | } | |
3878 | ||
3879 | char * | |
3880 | lt_extend_str (const char *orig_value, const char *add, int to_end) | |
3881 | { | |
3882 | char *new_value; | |
3883 | if (orig_value && *orig_value) | |
3884 | { | |
3885 | int orig_value_len = strlen (orig_value); | |
3886 | int add_len = strlen (add); | |
3887 | new_value = XMALLOC (char, add_len + orig_value_len + 1); | |
3888 | if (to_end) | |
3889 | { | |
3890 | strcpy (new_value, orig_value); | |
3891 | strcpy (new_value + orig_value_len, add); | |
3892 | } | |
3893 | else | |
3894 | { | |
3895 | strcpy (new_value, add); | |
3896 | strcpy (new_value + add_len, orig_value); | |
3897 | } | |
3898 | } | |
3899 | else | |
3900 | { | |
3901 | new_value = xstrdup (add); | |
3902 | } | |
3903 | return new_value; | |
3904 | } | |
3905 | ||
3906 | int | |
3907 | lt_split_name_value (const char *arg, char** name, char** value) | |
3908 | { | |
3909 | const char *p; | |
3910 | int len; | |
3911 | if (!arg || !*arg) | |
3912 | return 1; | |
3913 | ||
3914 | p = strchr (arg, (int)'='); | |
3915 | ||
3916 | if (!p) | |
3917 | return 1; | |
3918 | ||
3919 | *value = xstrdup (++p); | |
3920 | ||
3921 | len = strlen (arg) - strlen (*value); | |
3922 | *name = XMALLOC (char, len); | |
3923 | strncpy (*name, arg, len-1); | |
3924 | (*name)[len - 1] = '\0'; | |
3925 | ||
3926 | return 0; | |
3927 | } | |
3928 | ||
3929 | void | |
3930 | lt_opt_process_env_set (const char *arg) | |
3931 | { | |
3932 | char *name = NULL; | |
3933 | char *value = NULL; | |
3934 | ||
3935 | if (lt_split_name_value (arg, &name, &value) != 0) | |
3936 | { | |
3937 | XFREE (name); | |
3938 | XFREE (value); | |
3939 | lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); | |
3940 | } | |
3941 | ||
3942 | lt_setenv (name, value); | |
3943 | XFREE (name); | |
3944 | XFREE (value); | |
3945 | } | |
3946 | ||
3947 | void | |
3948 | lt_opt_process_env_prepend (const char *arg) | |
3949 | { | |
3950 | char *name = NULL; | |
3951 | char *value = NULL; | |
3952 | char *new_value = NULL; | |
3953 | ||
3954 | if (lt_split_name_value (arg, &name, &value) != 0) | |
3955 | { | |
3956 | XFREE (name); | |
3957 | XFREE (value); | |
3958 | lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); | |
3959 | } | |
3960 | ||
3961 | new_value = lt_extend_str (getenv (name), value, 0); | |
3962 | lt_setenv (name, new_value); | |
3963 | XFREE (new_value); | |
3964 | XFREE (name); | |
3965 | XFREE (value); | |
3966 | } | |
3967 | ||
3968 | void | |
3969 | lt_opt_process_env_append (const char *arg) | |
3970 | { | |
3971 | char *name = NULL; | |
3972 | char *value = NULL; | |
3973 | char *new_value = NULL; | |
3974 | ||
3975 | if (lt_split_name_value (arg, &name, &value) != 0) | |
3976 | { | |
3977 | XFREE (name); | |
3978 | XFREE (value); | |
3979 | lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); | |
3980 | } | |
3981 | ||
3982 | new_value = lt_extend_str (getenv (name), value, 1); | |
3983 | lt_setenv (name, new_value); | |
3984 | XFREE (new_value); | |
3985 | XFREE (name); | |
3986 | XFREE (value); | |
3987 | } | |
3988 | ||
3989 | void | |
3990 | lt_update_exe_path (const char *name, const char *value) | |
3991 | { | |
3992 | LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", | |
3993 | (name ? name : "<NULL>"), | |
3994 | (value ? value : "<NULL>"))); | |
3995 | ||
3996 | if (name && *name && value && *value) | |
3997 | { | |
3998 | char *new_value = lt_extend_str (getenv (name), value, 0); | |
3999 | /* some systems can't cope with a ':'-terminated path #' */ | |
4000 | int len = strlen (new_value); | |
4001 | while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) | |
4002 | { | |
4003 | new_value[len-1] = '\0'; | |
4004 | } | |
4005 | lt_setenv (name, new_value); | |
4006 | XFREE (new_value); | |
4007 | } | |
4008 | } | |
4009 | ||
4010 | void | |
4011 | lt_update_lib_path (const char *name, const char *value) | |
4012 | { | |
4013 | LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", | |
4014 | (name ? name : "<NULL>"), | |
4015 | (value ? value : "<NULL>"))); | |
4016 | ||
4017 | if (name && *name && value && *value) | |
4018 | { | |
4019 | char *new_value = lt_extend_str (getenv (name), value, 0); | |
4020 | lt_setenv (name, new_value); | |
4021 | XFREE (new_value); | |
4022 | } | |
4023 | } | |
4024 | ||
4025 | ||
3508 | 4026 | EOF |
3509 | 4027 | } |
3510 | 4028 | # end: func_emit_cwrapperexe_src |
3514 | 4032 | { |
3515 | 4033 | $opt_debug |
3516 | 4034 | case $host in |
3517 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) | |
4035 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) | |
3518 | 4036 | # It is impossible to link a dll without this setting, and |
3519 | 4037 | # we shouldn't force the makefile maintainer to figure out |
3520 | 4038 | # which system we are compiling for in order to pass an extra |
3958 | 4476 | -L*) |
3959 | 4477 | func_stripname '-L' '' "$arg" |
3960 | 4478 | dir=$func_stripname_result |
4479 | if test -z "$dir"; then | |
4480 | if test "$#" -gt 0; then | |
4481 | func_fatal_error "require no space between \`-L' and \`$1'" | |
4482 | else | |
4483 | func_fatal_error "need path for \`-L' option" | |
4484 | fi | |
4485 | fi | |
3961 | 4486 | # We need an absolute path. |
3962 | 4487 | case $dir in |
3963 | 4488 | [\\/]* | [A-Za-z]:[\\/]*) ;; |
3976 | 4501 | ;; |
3977 | 4502 | esac |
3978 | 4503 | case $host in |
3979 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) | |
4504 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) | |
3980 | 4505 | testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` |
3981 | 4506 | case :$dllsearchpath: in |
3982 | 4507 | *":$dir:"*) ;; |
4508 | ::) dllsearchpath=$dir;; | |
3983 | 4509 | *) dllsearchpath="$dllsearchpath:$dir";; |
3984 | 4510 | esac |
3985 | 4511 | case :$dllsearchpath: in |
3986 | 4512 | *":$testbindir:"*) ;; |
4513 | ::) dllsearchpath=$testbindir;; | |
3987 | 4514 | *) dllsearchpath="$dllsearchpath:$testbindir";; |
3988 | 4515 | esac |
3989 | 4516 | ;; |
3994 | 4521 | -l*) |
3995 | 4522 | if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then |
3996 | 4523 | case $host in |
3997 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) | |
4524 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) | |
3998 | 4525 | # These systems don't actually have a C or math library (as such) |
3999 | 4526 | continue |
4000 | 4527 | ;; |
4071 | 4598 | |
4072 | 4599 | -no-install) |
4073 | 4600 | case $host in |
4074 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*) | |
4601 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) | |
4075 | 4602 | # The PATH hackery in wrapper scripts is required on Windows |
4076 | 4603 | # and Darwin in order for the loader to find any dlls it needs. |
4077 | 4604 | func_warning "\`-no-install' is ignored for $host" |
5031 | 5558 | if test -n "$library_names" && |
5032 | 5559 | { test "$use_static_libs" = no || test -z "$old_library"; }; then |
5033 | 5560 | case $host in |
5034 | *cygwin* | *mingw*) | |
5561 | *cygwin* | *mingw* | *cegcc*) | |
5035 | 5562 | # No point in relinking DLLs because paths are not encoded |
5036 | 5563 | notinst_deplibs="$notinst_deplibs $lib" |
5037 | 5564 | need_relink=no |
5101 | 5628 | elif test -n "$soname_spec"; then |
5102 | 5629 | # bleh windows |
5103 | 5630 | case $host in |
5104 | *cygwin* | mingw*) | |
5631 | *cygwin* | mingw* | *cegcc*) | |
5105 | 5632 | func_arith $current - $age |
5106 | 5633 | major=$func_arith_result |
5107 | 5634 | versuffix="-$major" |
5883 | 6410 | tempremovelist=`$ECHO "$output_objdir/*"` |
5884 | 6411 | for p in $tempremovelist; do |
5885 | 6412 | case $p in |
5886 | *.$objext) | |
6413 | *.$objext | *.gcno) | |
5887 | 6414 | ;; |
5888 | 6415 | $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) |
5889 | 6416 | if test "X$precious_files_regex" != "X"; then |
5954 | 6481 | if test "$build_libtool_libs" = yes; then |
5955 | 6482 | if test -n "$rpath"; then |
5956 | 6483 | case $host in |
5957 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) | |
6484 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) | |
5958 | 6485 | # these systems don't actually have a c library (as such)! |
5959 | 6486 | ;; |
5960 | 6487 | *-*-rhapsody* | *-*-darwin1.[012]) |
6453 | 6980 | |
6454 | 6981 | orig_export_symbols= |
6455 | 6982 | case $host_os in |
6456 | cygwin* | mingw*) | |
6983 | cygwin* | mingw* | cegcc*) | |
6457 | 6984 | if test -n "$export_symbols" && test -z "$export_symbols_regex"; then |
6458 | 6985 | # exporting using user supplied symfile |
6459 | 6986 | if test "x`$SED 1q $export_symbols`" != xEXPORTS; then |
7078 | 7605 | esac |
7079 | 7606 | fi |
7080 | 7607 | case $host in |
7081 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) | |
7608 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) | |
7082 | 7609 | testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` |
7083 | 7610 | case :$dllsearchpath: in |
7084 | 7611 | *":$libdir:"*) ;; |
7612 | ::) dllsearchpath=$libdir;; | |
7085 | 7613 | *) dllsearchpath="$dllsearchpath:$libdir";; |
7086 | 7614 | esac |
7087 | 7615 | case :$dllsearchpath: in |
7088 | 7616 | *":$testbindir:"*) ;; |
7617 | ::) dllsearchpath=$testbindir;; | |
7089 | 7618 | *) dllsearchpath="$dllsearchpath:$testbindir";; |
7090 | 7619 | esac |
7091 | 7620 | ;; |
7155 | 7684 | wrappers_required=no |
7156 | 7685 | fi |
7157 | 7686 | ;; |
7687 | *cegcc) | |
7688 | # Disable wrappers for cegcc, we are cross compiling anyway. | |
7689 | wrappers_required=no | |
7690 | ;; | |
7158 | 7691 | *) |
7159 | 7692 | if test "$need_relink" = no || test "$build_libtool_libs" != yes; then |
7160 | 7693 | wrappers_required=no |
7307 | 7840 | |
7308 | 7841 | func_emit_cwrapperexe_src > $cwrappersource |
7309 | 7842 | |
7310 | # we should really use a build-platform specific compiler | |
7311 | # here, but OTOH, the wrappers (shell script and this C one) | |
7312 | # are only useful if you want to execute the "real" binary. | |
7313 | # Since the "real" binary is built for $host, then this | |
7314 | # wrapper might as well be built for $host, too. | |
7843 | # The wrapper executable is built using the $host compiler, | |
7844 | # because it contains $host paths and files. If cross- | |
7845 | # compiling, it, like the target executable, must be | |
7846 | # executed on the $host or under an emulation environment. | |
7315 | 7847 | $opt_dry_run || { |
7316 | 7848 | $LTCC $LTCFLAGS -o $cwrapper $cwrappersource |
7317 | 7849 | $STRIP $cwrapper |
7596 | 8128 | # place dlname in correct position for cygwin |
7597 | 8129 | tdlname=$dlname |
7598 | 8130 | case $host,$output,$installed,$module,$dlname in |
7599 | *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; | |
8131 | *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; | |
7600 | 8132 | esac |
7601 | 8133 | $ECHO > $output "\ |
7602 | 8134 | # $outputname - a libtool library file |
138 | 138 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
139 | 139 | NM = @NM@ |
140 | 140 | NMEDIT = @NMEDIT@ |
141 | OBJDUMP = @OBJDUMP@ | |
141 | 142 | OBJEXT = @OBJEXT@ |
142 | 143 | OTOOL = @OTOOL@ |
143 | 144 | OTOOL64 = @OTOOL64@ |
126 | 126 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
127 | 127 | NM = @NM@ |
128 | 128 | NMEDIT = @NMEDIT@ |
129 | OBJDUMP = @OBJDUMP@ | |
129 | 130 | OBJEXT = @OBJEXT@ |
130 | 131 | OTOOL = @OTOOL@ |
131 | 132 | OTOOL64 = @OTOOL64@ |
23 | 23 | socket.c \ |
24 | 24 | udp-bsd.h \ |
25 | 25 | udp-bsd.c \ |
26 | udp-turn.h \ | |
27 | udp-turn.c \ | |
26 | tcp-bsd.h \ | |
27 | tcp-bsd.c \ | |
28 | pseudossl.h \ | |
29 | pseudossl.c \ | |
30 | socks5.h \ | |
31 | socks5.c \ | |
32 | turn.h \ | |
33 | turn.c \ | |
28 | 34 | tcp-turn.h \ |
29 | 35 | tcp-turn.c |
30 | 36 | |
35 | 41 | |
36 | 42 | TESTS = $(check_PROGRAMS) |
37 | 43 | |
38 | pkginclude_HEADERS = socket.h udp-bsd.h udp-turn.h tcp-turn.h | |
44 | pkginclude_HEADERS = socket.h udp-bsd.h tcp-bsd.h pseudossl.h turn.h tcp-turn.h socks5.h | |
39 | 45 |
53 | 53 | CONFIG_CLEAN_FILES = |
54 | 54 | LTLIBRARIES = $(noinst_LTLIBRARIES) |
55 | 55 | libsocket_la_LIBADD = |
56 | am_libsocket_la_OBJECTS = socket.lo udp-bsd.lo udp-turn.lo tcp-turn.lo | |
56 | am_libsocket_la_OBJECTS = socket.lo udp-bsd.lo tcp-bsd.lo pseudossl.lo \ | |
57 | socks5.lo turn.lo tcp-turn.lo | |
57 | 58 | libsocket_la_OBJECTS = $(am_libsocket_la_OBJECTS) |
58 | 59 | test_bsd_SOURCES = test-bsd.c |
59 | 60 | test_bsd_OBJECTS = test-bsd.$(OBJEXT) |
138 | 139 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
139 | 140 | NM = @NM@ |
140 | 141 | NMEDIT = @NMEDIT@ |
142 | OBJDUMP = @OBJDUMP@ | |
141 | 143 | OBJEXT = @OBJEXT@ |
142 | 144 | OTOOL = @OTOOL@ |
143 | 145 | OTOOL64 = @OTOOL64@ |
237 | 239 | socket.c \ |
238 | 240 | udp-bsd.h \ |
239 | 241 | udp-bsd.c \ |
240 | udp-turn.h \ | |
241 | udp-turn.c \ | |
242 | tcp-bsd.h \ | |
243 | tcp-bsd.c \ | |
244 | pseudossl.h \ | |
245 | pseudossl.c \ | |
246 | socks5.h \ | |
247 | socks5.c \ | |
248 | turn.h \ | |
249 | turn.c \ | |
242 | 250 | tcp-turn.h \ |
243 | 251 | tcp-turn.c |
244 | 252 | |
245 | 253 | test_bsd_LDADD = $(COMMON_LDADD) |
246 | 254 | TESTS = $(check_PROGRAMS) |
247 | pkginclude_HEADERS = socket.h udp-bsd.h udp-turn.h tcp-turn.h | |
255 | pkginclude_HEADERS = socket.h udp-bsd.h tcp-bsd.h pseudossl.h turn.h tcp-turn.h socks5.h | |
248 | 256 | all: all-am |
249 | 257 | |
250 | 258 | .SUFFIXES: |
306 | 314 | distclean-compile: |
307 | 315 | -rm -f *.tab.c |
308 | 316 | |
317 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudossl.Plo@am__quote@ | |
309 | 318 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ |
319 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socks5.Plo@am__quote@ | |
320 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-bsd.Plo@am__quote@ | |
310 | 321 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-turn.Plo@am__quote@ |
311 | 322 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-bsd.Po@am__quote@ |
323 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/turn.Plo@am__quote@ | |
312 | 324 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-bsd.Plo@am__quote@ |
313 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-turn.Plo@am__quote@ | |
314 | 325 | |
315 | 326 | .c.o: |
316 | 327 | @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2006-2008 Collabora Ltd. | |
4 | * Contact: Dafydd Harries | |
5 | * Contact: Olivier Crete | |
6 | * (C) 2006, 2007 Nokia Corporation. All rights reserved. | |
7 | * Contact: Kai Vehmanen | |
8 | * | |
9 | * The contents of this file are subject to the Mozilla Public License Version | |
10 | * 1.1 (the "License"); you may not use this file except in compliance with | |
11 | * the License. You may obtain a copy of the License at | |
12 | * http://www.mozilla.org/MPL/ | |
13 | * | |
14 | * Software distributed under the License is distributed on an "AS IS" basis, | |
15 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
16 | * for the specific language governing rights and limitations under the | |
17 | * License. | |
18 | * | |
19 | * The Original Code is the Nice GLib ICE library. | |
20 | * | |
21 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
22 | * Corporation. All Rights Reserved. | |
23 | * | |
24 | * Contributors: | |
25 | * Dafydd Harries, Collabora Ltd. | |
26 | * Olivier Crete, Collabora Ltd. | |
27 | * Rémi Denis-Courmont, Nokia | |
28 | * Kai Vehmanen | |
29 | * | |
30 | * Alternatively, the contents of this file may be used under the terms of the | |
31 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
32 | * case the provisions of LGPL are applicable instead of those above. If you | |
33 | * wish to allow use of your version of this file only under the terms of the | |
34 | * LGPL and not to allow others to use your version of this file under the | |
35 | * MPL, indicate your decision by deleting the provisions above and replace | |
36 | * them with the notice and other provisions required by the LGPL. If you do | |
37 | * not delete the provisions above, a recipient may use your version of this | |
38 | * file under either the MPL or the LGPL. | |
39 | */ | |
40 | ||
41 | /* | |
42 | * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See | |
43 | * http://en.wikipedia.org/wiki/Berkeley_sockets.) | |
44 | */ | |
45 | #ifdef HAVE_CONFIG_H | |
46 | # include "config.h" | |
47 | #endif | |
48 | ||
49 | #include "pseudossl.h" | |
50 | ||
51 | #include <string.h> | |
52 | ||
53 | #ifndef G_OS_WIN32 | |
54 | #include <unistd.h> | |
55 | #endif | |
56 | ||
57 | typedef struct { | |
58 | gboolean handshaken; | |
59 | NiceSocket *base_socket; | |
60 | GQueue send_queue; | |
61 | } PseudoSSLPriv; | |
62 | ||
63 | ||
64 | struct to_be_sent { | |
65 | guint length; | |
66 | gchar *buf; | |
67 | NiceAddress to; | |
68 | }; | |
69 | ||
70 | ||
71 | static const gchar SSL_SERVER_HANDSHAKE[] = { | |
72 | 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, | |
73 | 0x46, 0x03, 0x01, 0x42, 0x85, 0x45, 0xa7, 0x27, | |
74 | 0xa9, 0x5d, 0xa0, 0xb3, 0xc5, 0xe7, 0x53, 0xda, | |
75 | 0x48, 0x2b, 0x3f, 0xc6, 0x5a, 0xca, 0x89, 0xc1, | |
76 | 0x58, 0x52, 0xa1, 0x78, 0x3c, 0x5b, 0x17, 0x46, | |
77 | 0x00, 0x85, 0x3f, 0x20, 0x0e, 0xd3, 0x06, 0x72, | |
78 | 0x5b, 0x5b, 0x1b, 0x5f, 0x15, 0xac, 0x13, 0xf9, | |
79 | 0x88, 0x53, 0x9d, 0x9b, 0xe8, 0x3d, 0x7b, 0x0c, | |
80 | 0x30, 0x32, 0x6e, 0x38, 0x4d, 0xa2, 0x75, 0x57, | |
81 | 0x41, 0x6c, 0x34, 0x5c, 0x00, 0x04, 0x00}; | |
82 | ||
83 | static const gchar SSL_CLIENT_HANDSHAKE[] = { | |
84 | 0x80, 0x46, 0x01, 0x03, 0x01, 0x00, 0x2d, 0x00, | |
85 | 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00, | |
86 | 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02, | |
87 | 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, | |
88 | 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0xfe, | |
89 | 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00, | |
90 | 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, | |
91 | 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc, | |
92 | 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea}; | |
93 | ||
94 | ||
95 | static void socket_close (NiceSocket *sock); | |
96 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
97 | guint len, gchar *buf); | |
98 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
99 | guint len, const gchar *buf); | |
100 | static gboolean socket_is_reliable (NiceSocket *sock); | |
101 | ||
102 | static void add_to_be_sent (NiceSocket *sock, const NiceAddress *to, | |
103 | const gchar *buf, guint len); | |
104 | static void free_to_be_sent (struct to_be_sent *tbs); | |
105 | ||
106 | ||
107 | NiceSocket * | |
108 | nice_pseudossl_socket_new (NiceAgent *agent, NiceSocket *base_socket) | |
109 | { | |
110 | PseudoSSLPriv *priv; | |
111 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
112 | sock->priv = priv = g_slice_new0 (PseudoSSLPriv); | |
113 | ||
114 | priv->handshaken = FALSE; | |
115 | priv->base_socket = base_socket; | |
116 | ||
117 | sock->fileno = priv->base_socket->fileno; | |
118 | sock->addr = priv->base_socket->addr; | |
119 | sock->send = socket_send; | |
120 | sock->recv = socket_recv; | |
121 | sock->is_reliable = socket_is_reliable; | |
122 | sock->close = socket_close; | |
123 | ||
124 | /* We send 'to' NULL because it will always be to an already connected | |
125 | * TCP base socket, which ignores the destination */ | |
126 | nice_socket_send (priv->base_socket, NULL, | |
127 | sizeof(SSL_CLIENT_HANDSHAKE), SSL_CLIENT_HANDSHAKE); | |
128 | ||
129 | return sock; | |
130 | } | |
131 | ||
132 | ||
133 | static void | |
134 | socket_close (NiceSocket *sock) | |
135 | { | |
136 | PseudoSSLPriv *priv = sock->priv; | |
137 | ||
138 | if (priv->base_socket) | |
139 | nice_socket_free (priv->base_socket); | |
140 | ||
141 | g_queue_foreach (&priv->send_queue, (GFunc) free_to_be_sent, NULL); | |
142 | g_queue_clear (&priv->send_queue); | |
143 | ||
144 | g_slice_free(PseudoSSLPriv, sock->priv); | |
145 | } | |
146 | ||
147 | ||
148 | static gint | |
149 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
150 | { | |
151 | PseudoSSLPriv *priv = sock->priv; | |
152 | ||
153 | if (priv->handshaken) { | |
154 | if (priv->base_socket) | |
155 | return nice_socket_recv (priv->base_socket, from, len, buf); | |
156 | } else { | |
157 | gchar data[sizeof(SSL_SERVER_HANDSHAKE)]; | |
158 | gint ret = -1; | |
159 | ||
160 | if (priv->base_socket) | |
161 | ret = nice_socket_recv (priv->base_socket, from, sizeof(data), data); | |
162 | ||
163 | if (ret <= 0) { | |
164 | return ret; | |
165 | } else if ((guint) ret == sizeof(SSL_SERVER_HANDSHAKE) && | |
166 | memcmp(SSL_SERVER_HANDSHAKE, data, sizeof(SSL_SERVER_HANDSHAKE)) == 0) { | |
167 | priv->handshaken = TRUE; | |
168 | struct to_be_sent *tbs = NULL; | |
169 | while ((tbs = g_queue_pop_head (&priv->send_queue))) { | |
170 | nice_socket_send (priv->base_socket, &tbs->to, tbs->length, tbs->buf); | |
171 | g_free (tbs->buf); | |
172 | g_slice_free (struct to_be_sent, tbs); | |
173 | } | |
174 | } else { | |
175 | if (priv->base_socket) | |
176 | nice_socket_free (priv->base_socket); | |
177 | priv->base_socket = NULL; | |
178 | ||
179 | return -1; | |
180 | } | |
181 | } | |
182 | return 0; | |
183 | } | |
184 | ||
185 | static gboolean | |
186 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
187 | guint len, const gchar *buf) | |
188 | { | |
189 | PseudoSSLPriv *priv = sock->priv; | |
190 | ||
191 | if (priv->handshaken) { | |
192 | if (priv->base_socket) | |
193 | return nice_socket_send (priv->base_socket, to, len, buf); | |
194 | else | |
195 | return FALSE; | |
196 | } else { | |
197 | add_to_be_sent (sock, to, buf, len); | |
198 | } | |
199 | return TRUE; | |
200 | } | |
201 | ||
202 | ||
203 | static gboolean | |
204 | socket_is_reliable (NiceSocket *sock) | |
205 | { | |
206 | return TRUE; | |
207 | } | |
208 | ||
209 | ||
210 | static void | |
211 | add_to_be_sent (NiceSocket *sock, const NiceAddress *to, | |
212 | const gchar *buf, guint len) | |
213 | { | |
214 | PseudoSSLPriv *priv = sock->priv; | |
215 | struct to_be_sent *tbs = NULL; | |
216 | ||
217 | if (len <= 0) | |
218 | return; | |
219 | ||
220 | tbs = g_slice_new0 (struct to_be_sent); | |
221 | tbs->buf = g_memdup (buf, len); | |
222 | tbs->length = len; | |
223 | if (to) | |
224 | tbs->to = *to; | |
225 | g_queue_push_tail (&priv->send_queue, tbs); | |
226 | ||
227 | } | |
228 | ||
229 | static void | |
230 | free_to_be_sent (struct to_be_sent *tbs) | |
231 | { | |
232 | g_free (tbs->buf); | |
233 | g_slice_free (struct to_be_sent, tbs); | |
234 | } |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2006, 2007 Collabora Ltd. | |
4 | * Contact: Dafydd Harries | |
5 | * (C) 2006, 2007 Nokia Corporation. All rights reserved. | |
6 | * Contact: Kai Vehmanen | |
7 | * | |
8 | * The contents of this file are subject to the Mozilla Public License Version | |
9 | * 1.1 (the "License"); you may not use this file except in compliance with | |
10 | * the License. You may obtain a copy of the License at | |
11 | * http://www.mozilla.org/MPL/ | |
12 | * | |
13 | * Software distributed under the License is distributed on an "AS IS" basis, | |
14 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
15 | * for the specific language governing rights and limitations under the | |
16 | * License. | |
17 | * | |
18 | * The Original Code is the Nice GLib ICE library. | |
19 | * | |
20 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
21 | * Corporation. All Rights Reserved. | |
22 | * | |
23 | * Contributors: | |
24 | * Dafydd Harries, Collabora Ltd. | |
25 | * | |
26 | * Alternatively, the contents of this file may be used under the terms of the | |
27 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
28 | * case the provisions of LGPL are applicable instead of those above. If you | |
29 | * wish to allow use of your version of this file only under the terms of the | |
30 | * LGPL and not to allow others to use your version of this file under the | |
31 | * MPL, indicate your decision by deleting the provisions above and replace | |
32 | * them with the notice and other provisions required by the LGPL. If you do | |
33 | * not delete the provisions above, a recipient may use your version of this | |
34 | * file under either the MPL or the LGPL. | |
35 | */ | |
36 | ||
37 | #ifndef _PSEUDOSSL_H | |
38 | #define _PSEUDOSSL_H | |
39 | ||
40 | #include "socket.h" | |
41 | #include "agent.h" | |
42 | ||
43 | G_BEGIN_DECLS | |
44 | ||
45 | ||
46 | NiceSocket * | |
47 | nice_pseudossl_socket_new (NiceAgent *agent, NiceSocket *base_socket); | |
48 | ||
49 | ||
50 | G_END_DECLS | |
51 | ||
52 | #endif /* _PSEUDOSSL_H */ | |
53 |
44 | 44 | |
45 | 45 | |
46 | 46 | gint |
47 | nice_socket_recv ( | |
48 | NiceSocket *sock, | |
49 | NiceAddress *from, | |
50 | guint len, | |
51 | gchar *buf) | |
47 | nice_socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
52 | 48 | { |
53 | 49 | return sock->recv (sock, from, len, buf); |
54 | 50 | } |
55 | 51 | |
56 | 52 | gboolean |
57 | nice_socket_send ( | |
58 | NiceSocket *sock, | |
59 | const NiceAddress *to, | |
60 | guint len, | |
61 | const gchar *buf) | |
53 | nice_socket_send (NiceSocket *sock, const NiceAddress *to, | |
54 | guint len, const gchar *buf) | |
62 | 55 | { |
63 | 56 | return sock->send (sock, to, len, buf); |
64 | 57 | } |
68 | 68 | |
69 | 69 | G_GNUC_WARN_UNUSED_RESULT |
70 | 70 | gint |
71 | nice_socket_recv ( | |
72 | NiceSocket *sock, | |
73 | NiceAddress *from, | |
74 | guint len, | |
75 | gchar *buf); | |
71 | nice_socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf); | |
76 | 72 | |
77 | 73 | gboolean |
78 | nice_socket_send ( | |
79 | NiceSocket *sock, | |
80 | const NiceAddress *to, | |
81 | guint len, | |
82 | const gchar *buf); | |
74 | nice_socket_send (NiceSocket *sock, const NiceAddress *to, | |
75 | guint len, const gchar *buf); | |
83 | 76 | |
84 | 77 | gboolean |
85 | 78 | nice_socket_is_reliable (NiceSocket *sock); |
89 | 82 | nice_socket_free (NiceSocket *sock); |
90 | 83 | |
91 | 84 | #include "udp-bsd.h" |
92 | #include "udp-turn.h" | |
85 | #include "tcp-bsd.h" | |
86 | #include "pseudossl.h" | |
87 | #include "socks5.h" | |
88 | #include "turn.h" | |
93 | 89 | #include "tcp-turn.h" |
94 | 90 | |
95 | 91 | G_END_DECLS |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * Contact: Youness Alaoui | |
5 | * (C) 2008 Nokia Corporation. All rights reserved. | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Youness Alaoui, Collabora Ltd. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
27 | * case the provisions of LGPL are applicable instead of those above. If you | |
28 | * wish to allow use of your version of this file only under the terms of the | |
29 | * LGPL and not to allow others to use your version of this file under the | |
30 | * MPL, indicate your decision by deleting the provisions above and replace | |
31 | * them with the notice and other provisions required by the LGPL. If you do | |
32 | * not delete the provisions above, a recipient may use your version of this | |
33 | * file under either the MPL or the LGPL. | |
34 | */ | |
35 | ||
36 | /* | |
37 | * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See | |
38 | * http://en.wikipedia.org/wiki/Berkeley_sockets.) | |
39 | */ | |
40 | #ifdef HAVE_CONFIG_H | |
41 | # include "config.h" | |
42 | #endif | |
43 | ||
44 | #include "socks5.h" | |
45 | ||
46 | #include <string.h> | |
47 | ||
48 | #ifndef G_OS_WIN32 | |
49 | #include <unistd.h> | |
50 | #endif | |
51 | ||
52 | typedef enum { | |
53 | SOCKS_STATE_INIT, | |
54 | SOCKS_STATE_AUTH, | |
55 | SOCKS_STATE_CONNECT, | |
56 | SOCKS_STATE_CONNECTED, | |
57 | SOCKS_STATE_ERROR | |
58 | } SocksState; | |
59 | ||
60 | typedef struct { | |
61 | SocksState state; | |
62 | NiceSocket *base_socket; | |
63 | NiceAddress addr; | |
64 | gchar *username; | |
65 | gchar *password; | |
66 | GQueue send_queue; | |
67 | } Socks5Priv; | |
68 | ||
69 | ||
70 | struct to_be_sent { | |
71 | guint length; | |
72 | gchar *buf; | |
73 | NiceAddress to; | |
74 | }; | |
75 | ||
76 | ||
77 | static void socket_close (NiceSocket *sock); | |
78 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
79 | guint len, gchar *buf); | |
80 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
81 | guint len, const gchar *buf); | |
82 | static gboolean socket_is_reliable (NiceSocket *sock); | |
83 | ||
84 | static void add_to_be_sent (NiceSocket *sock, const NiceAddress *to, | |
85 | const gchar *buf, guint len); | |
86 | static void free_to_be_sent (struct to_be_sent *tbs); | |
87 | ||
88 | ||
89 | NiceSocket * | |
90 | nice_socks5_socket_new (NiceSocket *base_socket, | |
91 | NiceAddress *addr, gchar *username, gchar *password) | |
92 | { | |
93 | Socks5Priv *priv; | |
94 | NiceSocket *sock = NULL; | |
95 | ||
96 | if (addr) { | |
97 | sock = g_slice_new0 (NiceSocket); | |
98 | sock->priv = priv = g_slice_new0 (Socks5Priv); | |
99 | ||
100 | priv->base_socket = base_socket; | |
101 | priv->addr = *addr; | |
102 | priv->username = g_strdup (username); | |
103 | priv->password = g_strdup (password); | |
104 | ||
105 | sock->fileno = priv->base_socket->fileno; | |
106 | sock->addr = priv->base_socket->addr; | |
107 | sock->send = socket_send; | |
108 | sock->recv = socket_recv; | |
109 | sock->is_reliable = socket_is_reliable; | |
110 | sock->close = socket_close; | |
111 | ||
112 | /* Send SOCKS5 handshake */ | |
113 | { | |
114 | gchar msg[4]; | |
115 | gint len = 3; | |
116 | ||
117 | msg[0] = 0x05; /* SOCKS version */ | |
118 | msg[1] = 0x01; /* number of methods supported */ | |
119 | msg[2] = 0x00; /* no authentication method*/ | |
120 | ||
121 | g_debug ("user/pass : %s - %s", username, password); | |
122 | /* add support for authentication method */ | |
123 | if (username || password) { | |
124 | msg[1] = 0x02; /* number of methods supported */ | |
125 | msg[3] = 0x02; /* authentication method */ | |
126 | len++; | |
127 | } | |
128 | ||
129 | /* We send 'to' NULL because it will always be to an already connected | |
130 | * TCP base socket, which ignores the destination */ | |
131 | nice_socket_send (priv->base_socket, NULL, len, msg); | |
132 | priv->state = SOCKS_STATE_INIT; | |
133 | } | |
134 | } | |
135 | ||
136 | return sock; | |
137 | } | |
138 | ||
139 | ||
140 | static void | |
141 | socket_close (NiceSocket *sock) | |
142 | { | |
143 | Socks5Priv *priv = sock->priv; | |
144 | ||
145 | if (priv->base_socket) | |
146 | nice_socket_free (priv->base_socket); | |
147 | ||
148 | if (priv->username) | |
149 | g_free (priv->username); | |
150 | ||
151 | if (priv->password) | |
152 | g_free (priv->password); | |
153 | ||
154 | g_queue_foreach (&priv->send_queue, (GFunc) free_to_be_sent, NULL); | |
155 | g_queue_clear (&priv->send_queue); | |
156 | ||
157 | g_slice_free(Socks5Priv, sock->priv); | |
158 | } | |
159 | ||
160 | ||
161 | static gint | |
162 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
163 | { | |
164 | Socks5Priv *priv = sock->priv; | |
165 | ||
166 | switch (priv->state) { | |
167 | case SOCKS_STATE_CONNECTED: | |
168 | if (priv->base_socket) | |
169 | return nice_socket_recv (priv->base_socket, from, len, buf); | |
170 | break; | |
171 | case SOCKS_STATE_INIT: | |
172 | { | |
173 | gchar data[2]; | |
174 | gint ret = -1; | |
175 | ||
176 | nice_debug ("Socks5 state Init"); | |
177 | ||
178 | if (priv->base_socket) | |
179 | ret = nice_socket_recv (priv->base_socket, from, sizeof(data), data); | |
180 | ||
181 | if (ret <= 0) { | |
182 | return ret; | |
183 | } else if(ret == sizeof(data)) { | |
184 | if (data[0] == 0x05) { | |
185 | if (data[1] == 0x02) { | |
186 | gchar msg[515]; | |
187 | gint len = 0; | |
188 | ||
189 | if (priv->username || priv->password) { | |
190 | gint ulen = 0; | |
191 | gint plen = 0; | |
192 | ||
193 | if (priv->username) | |
194 | ulen = strlen (priv->username); | |
195 | ||
196 | if (priv->password) | |
197 | plen = strlen (priv->password); | |
198 | ||
199 | msg[len++] = 0x01; /* auth version */ | |
200 | msg[len++] = ulen; /* username length */ | |
201 | memcpy (msg + len, priv->username, ulen); /* Username */ | |
202 | len += ulen; | |
203 | msg[len++] = plen; /* Password length */ | |
204 | memcpy (msg + len, priv->password, plen); /* Password */ | |
205 | len += plen; | |
206 | ||
207 | nice_socket_send (priv->base_socket, NULL, len, msg); | |
208 | priv->state = SOCKS_STATE_AUTH; | |
209 | } else { | |
210 | /* Authentication required but no auth info available */ | |
211 | goto error; | |
212 | } | |
213 | } else if (data[1] == 0x00) { | |
214 | goto send_connect; | |
215 | } else { | |
216 | /* method not supported by socks server */ | |
217 | goto error; | |
218 | } | |
219 | } else { | |
220 | /* invalid SOCKS server version */ | |
221 | goto error; | |
222 | } | |
223 | } else { | |
224 | /* read error */ | |
225 | goto error; | |
226 | } | |
227 | } | |
228 | break; | |
229 | case SOCKS_STATE_AUTH: | |
230 | { | |
231 | gchar data[2]; | |
232 | gint ret = -1; | |
233 | ||
234 | nice_debug ("Socks5 state auth"); | |
235 | if (priv->base_socket) | |
236 | ret = nice_socket_recv (priv->base_socket, from, sizeof(data), data); | |
237 | ||
238 | if (ret <= 0) { | |
239 | return ret; | |
240 | } else if(ret == sizeof(data)) { | |
241 | if (data[0] == 0x01 && data[1] == 0x00) { | |
242 | /* Authenticated */ | |
243 | goto send_connect; | |
244 | } else { | |
245 | /* Authentication failed */ | |
246 | goto error; | |
247 | } | |
248 | } | |
249 | } | |
250 | break; | |
251 | case SOCKS_STATE_CONNECT: | |
252 | { | |
253 | gchar data[22]; | |
254 | gint ret = -1; | |
255 | ||
256 | nice_debug ("Socks5 state connect"); | |
257 | if (priv->base_socket) | |
258 | ret = nice_socket_recv (priv->base_socket, from, 4, data); | |
259 | ||
260 | if (ret <= 0) { | |
261 | return ret; | |
262 | } else if(ret == 4) { | |
263 | if (data[0] == 0x05) { | |
264 | switch (data[1]) { | |
265 | case 0x00: | |
266 | if (data[2] == 0x00) { | |
267 | struct to_be_sent *tbs = NULL; | |
268 | switch (data[3]) { | |
269 | case 0x01: /* IPV4 bound address */ | |
270 | ret = nice_socket_recv (priv->base_socket, from, 6, data); | |
271 | if (ret != 6) { | |
272 | /* Could not read server bound address */ | |
273 | goto error; | |
274 | } | |
275 | break; | |
276 | case 0x04: /* IPV6 bound address */ | |
277 | ret = nice_socket_recv (priv->base_socket, from, 18, data); | |
278 | if (ret != 18) { | |
279 | /* Could not read server bound address */ | |
280 | goto error; | |
281 | } | |
282 | break; | |
283 | default: | |
284 | /* Unsupported address type */ | |
285 | goto error; | |
286 | } | |
287 | while ((tbs = g_queue_pop_head (&priv->send_queue))) { | |
288 | nice_socket_send (priv->base_socket, &tbs->to, | |
289 | tbs->length, tbs->buf); | |
290 | g_free (tbs->buf); | |
291 | g_slice_free (struct to_be_sent, tbs); | |
292 | } | |
293 | priv->state = SOCKS_STATE_CONNECTED; | |
294 | } else { | |
295 | /* Wrong reserved value */ | |
296 | goto error; | |
297 | } | |
298 | break; | |
299 | case 0x01: /* general SOCKS server failure */ | |
300 | case 0x02: /* connection not allowed by ruleset */ | |
301 | case 0x03: /* Network unreachable */ | |
302 | case 0x04: /* Host unreachable */ | |
303 | case 0x05: /* Connection refused */ | |
304 | case 0x06: /* TTL expired */ | |
305 | case 0x07: /* Command not supported */ | |
306 | case 0x08: /* Address type not supported */ | |
307 | default: /* Unknown error */ | |
308 | goto error; | |
309 | break; | |
310 | } | |
311 | } else { | |
312 | /* Wrong server version */ | |
313 | goto error; | |
314 | } | |
315 | } else { | |
316 | /* Invalid data received */ | |
317 | goto error; | |
318 | } | |
319 | } | |
320 | break; | |
321 | default: | |
322 | /* Unknown status */ | |
323 | goto error; | |
324 | } | |
325 | ||
326 | return 0; | |
327 | ||
328 | send_connect: | |
329 | { | |
330 | gchar msg[22]; | |
331 | gint len = 0; | |
332 | struct sockaddr_storage name; | |
333 | nice_address_copy_to_sockaddr(&priv->addr, (struct sockaddr *)&name); | |
334 | ||
335 | msg[len++] = 0x05; /* SOCKS version */ | |
336 | msg[len++] = 0x01; /* connect command */ | |
337 | msg[len++] = 0x00; /* reserved */ | |
338 | if (name.ss_family == AF_INET) { | |
339 | msg[len++] = 0x01; /* IPV4 address type */ | |
340 | /* Address */ | |
341 | memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_addr, 4); | |
342 | len += 4; | |
343 | /* Port */ | |
344 | memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_port, 2); | |
345 | len += 2; | |
346 | } else if (name.ss_family == AF_INET6) { | |
347 | msg[len++] = 0x04; /* IPV6 address type */ | |
348 | /* Address */ | |
349 | memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_addr, 16); | |
350 | len += 16; | |
351 | /* Port */ | |
352 | memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_port, 2); | |
353 | len += 2; | |
354 | } | |
355 | ||
356 | nice_socket_send (priv->base_socket, NULL, len, msg); | |
357 | priv->state = SOCKS_STATE_CONNECT; | |
358 | ||
359 | return 0; | |
360 | } | |
361 | error: | |
362 | nice_debug ("Socks5 error"); | |
363 | if (priv->base_socket) | |
364 | nice_socket_free (priv->base_socket); | |
365 | priv->base_socket = NULL; | |
366 | priv->state = SOCKS_STATE_ERROR; | |
367 | ||
368 | return -1; | |
369 | } | |
370 | ||
371 | static gboolean | |
372 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
373 | guint len, const gchar *buf) | |
374 | { | |
375 | Socks5Priv *priv = sock->priv; | |
376 | ||
377 | if (priv->state == SOCKS_STATE_CONNECTED) { | |
378 | if (priv->base_socket) | |
379 | return nice_socket_send (priv->base_socket, to, len, buf); | |
380 | else | |
381 | return FALSE; | |
382 | } else if (priv->state == SOCKS_STATE_ERROR) { | |
383 | return FALSE; | |
384 | } else { | |
385 | add_to_be_sent (sock, to, buf, len); | |
386 | } | |
387 | return TRUE; | |
388 | } | |
389 | ||
390 | ||
391 | static gboolean | |
392 | socket_is_reliable (NiceSocket *sock) | |
393 | { | |
394 | return TRUE; | |
395 | } | |
396 | ||
397 | ||
398 | static void | |
399 | add_to_be_sent (NiceSocket *sock, const NiceAddress *to, | |
400 | const gchar *buf, guint len) | |
401 | { | |
402 | Socks5Priv *priv = sock->priv; | |
403 | struct to_be_sent *tbs = NULL; | |
404 | ||
405 | if (len <= 0) | |
406 | return; | |
407 | ||
408 | tbs = g_slice_new0 (struct to_be_sent); | |
409 | tbs->buf = g_memdup (buf, len); | |
410 | tbs->length = len; | |
411 | if (to) | |
412 | tbs->to = *to; | |
413 | g_queue_push_tail (&priv->send_queue, tbs); | |
414 | ||
415 | } | |
416 | ||
417 | ||
418 | static void | |
419 | free_to_be_sent (struct to_be_sent *tbs) | |
420 | { | |
421 | g_free (tbs->buf); | |
422 | g_slice_free (struct to_be_sent, tbs); | |
423 | } |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * Contact: Youness Alaoui | |
5 | * (C) 2008 Nokia Corporation. All rights reserved. | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Youness Alaoui, Collabora Ltd. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
27 | * case the provisions of LGPL are applicable instead of those above. If you | |
28 | * wish to allow use of your version of this file only under the terms of the | |
29 | * LGPL and not to allow others to use your version of this file under the | |
30 | * MPL, indicate your decision by deleting the provisions above and replace | |
31 | * them with the notice and other provisions required by the LGPL. If you do | |
32 | * not delete the provisions above, a recipient may use your version of this | |
33 | * file under either the MPL or the LGPL. | |
34 | */ | |
35 | ||
36 | #ifndef _SOCKS5_H | |
37 | #define _SOCKS5_H | |
38 | ||
39 | #include "socket.h" | |
40 | #include "agent.h" | |
41 | ||
42 | G_BEGIN_DECLS | |
43 | ||
44 | ||
45 | NiceSocket * | |
46 | nice_socks5_socket_new (NiceSocket *base_socket, | |
47 | NiceAddress *addr, gchar *username, gchar *password); | |
48 | ||
49 | ||
50 | G_END_DECLS | |
51 | ||
52 | #endif /* _SOCKS5_H */ | |
53 |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2006-2008 Collabora Ltd. | |
4 | * Contact: Dafydd Harries | |
5 | * Contact: Olivier Crete | |
6 | * (C) 2006, 2007 Nokia Corporation. All rights reserved. | |
7 | * Contact: Kai Vehmanen | |
8 | * | |
9 | * The contents of this file are subject to the Mozilla Public License Version | |
10 | * 1.1 (the "License"); you may not use this file except in compliance with | |
11 | * the License. You may obtain a copy of the License at | |
12 | * http://www.mozilla.org/MPL/ | |
13 | * | |
14 | * Software distributed under the License is distributed on an "AS IS" basis, | |
15 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
16 | * for the specific language governing rights and limitations under the | |
17 | * License. | |
18 | * | |
19 | * The Original Code is the Nice GLib ICE library. | |
20 | * | |
21 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
22 | * Corporation. All Rights Reserved. | |
23 | * | |
24 | * Contributors: | |
25 | * Dafydd Harries, Collabora Ltd. | |
26 | * Olivier Crete, Collabora Ltd. | |
27 | * Rémi Denis-Courmont, Nokia | |
28 | * Kai Vehmanen | |
29 | * | |
30 | * Alternatively, the contents of this file may be used under the terms of the | |
31 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
32 | * case the provisions of LGPL are applicable instead of those above. If you | |
33 | * wish to allow use of your version of this file only under the terms of the | |
34 | * LGPL and not to allow others to use your version of this file under the | |
35 | * MPL, indicate your decision by deleting the provisions above and replace | |
36 | * them with the notice and other provisions required by the LGPL. If you do | |
37 | * not delete the provisions above, a recipient may use your version of this | |
38 | * file under either the MPL or the LGPL. | |
39 | */ | |
40 | ||
41 | /* | |
42 | * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See | |
43 | * http://en.wikipedia.org/wiki/Berkeley_sockets.) | |
44 | */ | |
45 | #ifdef HAVE_CONFIG_H | |
46 | # include "config.h" | |
47 | #endif | |
48 | ||
49 | #include "tcp-bsd.h" | |
50 | #include "agent-priv.h" | |
51 | ||
52 | #include <string.h> | |
53 | #include <errno.h> | |
54 | #include <fcntl.h> | |
55 | ||
56 | #ifndef G_OS_WIN32 | |
57 | #include <unistd.h> | |
58 | #endif | |
59 | ||
60 | typedef struct { | |
61 | NiceAgent *agent; | |
62 | NiceAddress server_addr; | |
63 | GQueue send_queue; | |
64 | GMainContext *context; | |
65 | GIOChannel *io_channel; | |
66 | GSource *io_source; | |
67 | } TcpPriv; | |
68 | ||
69 | struct to_be_sent { | |
70 | guint length; | |
71 | gchar *buf; | |
72 | }; | |
73 | ||
74 | ||
75 | static void socket_close (NiceSocket *sock); | |
76 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
77 | guint len, gchar *buf); | |
78 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
79 | guint len, const gchar *buf); | |
80 | static gboolean socket_is_reliable (NiceSocket *sock); | |
81 | ||
82 | ||
83 | static void add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, | |
84 | gboolean head); | |
85 | static void free_to_be_sent (struct to_be_sent *tbs); | |
86 | static gboolean socket_send_more (GIOChannel *source, GIOCondition condition, | |
87 | gpointer data); | |
88 | ||
89 | NiceSocket * | |
90 | nice_tcp_bsd_socket_new (NiceAgent *agent, GMainContext *ctx, NiceAddress *addr) | |
91 | { | |
92 | int sockfd = -1; | |
93 | int ret; | |
94 | struct sockaddr_storage name; | |
95 | guint name_len = sizeof (name); | |
96 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
97 | TcpPriv *priv; | |
98 | ||
99 | if (addr != NULL) { | |
100 | nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); | |
101 | } else { | |
102 | memset (&name, 0, sizeof (name)); | |
103 | name.ss_family = AF_UNSPEC; | |
104 | } | |
105 | ||
106 | if ((sockfd == -1) && | |
107 | ((name.ss_family == AF_UNSPEC) || | |
108 | (name.ss_family == AF_INET))) { | |
109 | sockfd = socket (PF_INET, SOCK_STREAM, 0); | |
110 | name.ss_family = AF_INET; | |
111 | #ifdef HAVE_SA_LEN | |
112 | name.ss_len = sizeof (struct sockaddr_in); | |
113 | #endif | |
114 | } | |
115 | ||
116 | if (sockfd == -1) { | |
117 | g_slice_free (NiceSocket, sock); | |
118 | return NULL; | |
119 | } | |
120 | ||
121 | #ifdef FD_CLOEXEC | |
122 | fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC); | |
123 | #endif | |
124 | #ifdef O_NONBLOCK | |
125 | fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK); | |
126 | #endif | |
127 | ||
128 | name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
129 | sizeof(struct sockaddr_in6); | |
130 | ret = connect (sockfd, (const struct sockaddr *)&name, name_len); | |
131 | ||
132 | #ifdef G_OS_WIN32 | |
133 | if (ret < 0 && WSAGetLastError () != WSAEINPROGRESS) { | |
134 | closesocket (sockfd); | |
135 | #else | |
136 | if (ret < 0 && errno != EINPROGRESS) { | |
137 | close (sockfd); | |
138 | #endif | |
139 | g_slice_free (NiceSocket, sock); | |
140 | return NULL; | |
141 | } | |
142 | ||
143 | name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
144 | sizeof(struct sockaddr_in6); | |
145 | if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) { | |
146 | g_slice_free (NiceSocket, sock); | |
147 | #ifdef G_OS_WIN32 | |
148 | closesocket(sockfd); | |
149 | #else | |
150 | close (sockfd); | |
151 | #endif | |
152 | return NULL; | |
153 | } | |
154 | ||
155 | nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name); | |
156 | ||
157 | sock->priv = priv = g_slice_new0 (TcpPriv); | |
158 | ||
159 | priv->agent = agent; | |
160 | priv->context = ctx; | |
161 | priv->server_addr = *addr; | |
162 | ||
163 | sock->fileno = sockfd; | |
164 | sock->send = socket_send; | |
165 | sock->recv = socket_recv; | |
166 | sock->is_reliable = socket_is_reliable; | |
167 | sock->close = socket_close; | |
168 | ||
169 | return sock; | |
170 | } | |
171 | ||
172 | ||
173 | static void | |
174 | socket_close (NiceSocket *sock) | |
175 | { | |
176 | TcpPriv *priv = sock->priv; | |
177 | ||
178 | #ifdef G_OS_WIN32 | |
179 | closesocket(sock->fileno); | |
180 | #else | |
181 | close (sock->fileno); | |
182 | #endif | |
183 | if (priv->io_source) { | |
184 | g_source_destroy (priv->io_source); | |
185 | g_source_unref (priv->io_source); | |
186 | } | |
187 | if (priv->io_channel) | |
188 | g_io_channel_unref (priv->io_channel); | |
189 | g_queue_foreach (&priv->send_queue, (GFunc) free_to_be_sent, NULL); | |
190 | g_queue_clear (&priv->send_queue); | |
191 | ||
192 | g_slice_free(TcpPriv, sock->priv); | |
193 | } | |
194 | ||
195 | static gint | |
196 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
197 | { | |
198 | TcpPriv *priv = sock->priv; | |
199 | int ret; | |
200 | ||
201 | ret = recv (sock->fileno, buf, len, 0); | |
202 | ||
203 | /* recv returns 0 when the peer performed a shutdown.. we must return -1 here | |
204 | * so that the agent destroys the g_source */ | |
205 | if (ret == 0) | |
206 | return -1; | |
207 | ||
208 | if (ret < 0) { | |
209 | #ifdef G_OS_WIN32 | |
210 | if (WSAGetLastError () == WSAEWOULDBLOCK) | |
211 | #else | |
212 | if (errno == EAGAIN) | |
213 | #endif | |
214 | return 0; | |
215 | else | |
216 | return ret; | |
217 | } | |
218 | ||
219 | if (from) | |
220 | *from = priv->server_addr; | |
221 | return ret; | |
222 | } | |
223 | ||
224 | ||
225 | static gboolean | |
226 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
227 | guint len, const gchar *buf) | |
228 | { | |
229 | TcpPriv *priv = sock->priv; | |
230 | int ret; | |
231 | ||
232 | /* First try to send the data, don't send it later if it can be sent now | |
233 | this way we avoid allocating memory on every send */ | |
234 | if (g_queue_is_empty (&priv->send_queue)) { | |
235 | ret = send (sock->fileno, buf, len, 0); | |
236 | ||
237 | if (ret < 0) { | |
238 | #ifdef G_OS_WIN32 | |
239 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
240 | #else | |
241 | if (errno == EAGAIN) { | |
242 | #endif | |
243 | add_to_be_sent (sock, buf, len, FALSE); | |
244 | return TRUE; | |
245 | } else { | |
246 | return FALSE; | |
247 | } | |
248 | } else if ((guint)ret < len) { | |
249 | add_to_be_sent (sock, buf + ret, len - ret, FALSE); | |
250 | return TRUE; | |
251 | } | |
252 | } else { | |
253 | add_to_be_sent (sock, buf, len, FALSE); | |
254 | } | |
255 | ||
256 | return TRUE; | |
257 | } | |
258 | ||
259 | static gboolean | |
260 | socket_is_reliable (NiceSocket *sock) | |
261 | { | |
262 | return TRUE; | |
263 | } | |
264 | ||
265 | ||
266 | /* | |
267 | * Returns: | |
268 | * -1 = error | |
269 | * 0 = have more to send | |
270 | * 1 = sent everything | |
271 | */ | |
272 | ||
273 | static gboolean | |
274 | socket_send_more ( | |
275 | GIOChannel *source, | |
276 | GIOCondition condition, | |
277 | gpointer data) | |
278 | { | |
279 | NiceSocket *sock = (NiceSocket *) data; | |
280 | TcpPriv *priv = sock->priv; | |
281 | struct to_be_sent *tbs = NULL; | |
282 | ||
283 | g_static_rec_mutex_lock (&priv->agent->mutex); | |
284 | ||
285 | while ((tbs = g_queue_pop_head (&priv->send_queue))) { | |
286 | int ret; | |
287 | ||
288 | ret = send (sock->fileno, tbs->buf, tbs->length, 0); | |
289 | ||
290 | if (ret < 0) { | |
291 | #ifdef G_OS_WIN32 | |
292 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
293 | #else | |
294 | if (errno == EAGAIN) { | |
295 | #endif | |
296 | add_to_be_sent (sock, tbs->buf, tbs->length, TRUE); | |
297 | g_free (tbs->buf); | |
298 | g_slice_free (struct to_be_sent, tbs); | |
299 | break; | |
300 | } | |
301 | } else if (ret < (int) tbs->length) { | |
302 | add_to_be_sent (sock, tbs->buf + ret, tbs->length - ret, TRUE); | |
303 | g_free (tbs->buf); | |
304 | g_slice_free (struct to_be_sent, tbs); | |
305 | break; | |
306 | } | |
307 | ||
308 | g_free (tbs->buf); | |
309 | g_slice_free (struct to_be_sent, tbs); | |
310 | } | |
311 | ||
312 | if (g_queue_is_empty (&priv->send_queue)) { | |
313 | g_io_channel_unref (priv->io_channel); | |
314 | priv->io_channel = NULL; | |
315 | g_source_destroy (priv->io_source); | |
316 | g_source_unref (priv->io_source); | |
317 | priv->io_source = NULL; | |
318 | ||
319 | g_static_rec_mutex_unlock (&priv->agent->mutex); | |
320 | return FALSE; | |
321 | } | |
322 | ||
323 | g_static_rec_mutex_unlock (&priv->agent->mutex); | |
324 | return TRUE; | |
325 | } | |
326 | ||
327 | ||
328 | static void | |
329 | add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head) | |
330 | { | |
331 | TcpPriv *priv = sock->priv; | |
332 | struct to_be_sent *tbs = NULL; | |
333 | ||
334 | if (len <= 0) | |
335 | return; | |
336 | ||
337 | tbs = g_slice_new0 (struct to_be_sent); | |
338 | tbs->buf = g_memdup (buf, len); | |
339 | tbs->length = len; | |
340 | if (head) | |
341 | g_queue_push_head (&priv->send_queue, tbs); | |
342 | else | |
343 | g_queue_push_tail (&priv->send_queue, tbs); | |
344 | ||
345 | if (priv->io_channel == NULL) { | |
346 | priv->io_channel = g_io_channel_unix_new (sock->fileno); | |
347 | priv->io_source = g_io_create_watch (priv->io_channel, G_IO_OUT); | |
348 | g_source_set_callback (priv->io_source, (GSourceFunc) socket_send_more, | |
349 | sock, NULL); | |
350 | g_source_attach (priv->io_source, priv->context); | |
351 | } | |
352 | } | |
353 | ||
354 | ||
355 | ||
356 | static void | |
357 | free_to_be_sent (struct to_be_sent *tbs) | |
358 | { | |
359 | g_free (tbs->buf); | |
360 | g_slice_free (struct to_be_sent, tbs); | |
361 | } | |
362 |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2006, 2007 Collabora Ltd. | |
4 | * Contact: Dafydd Harries | |
5 | * (C) 2006, 2007 Nokia Corporation. All rights reserved. | |
6 | * Contact: Kai Vehmanen | |
7 | * | |
8 | * The contents of this file are subject to the Mozilla Public License Version | |
9 | * 1.1 (the "License"); you may not use this file except in compliance with | |
10 | * the License. You may obtain a copy of the License at | |
11 | * http://www.mozilla.org/MPL/ | |
12 | * | |
13 | * Software distributed under the License is distributed on an "AS IS" basis, | |
14 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
15 | * for the specific language governing rights and limitations under the | |
16 | * License. | |
17 | * | |
18 | * The Original Code is the Nice GLib ICE library. | |
19 | * | |
20 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
21 | * Corporation. All Rights Reserved. | |
22 | * | |
23 | * Contributors: | |
24 | * Dafydd Harries, Collabora Ltd. | |
25 | * | |
26 | * Alternatively, the contents of this file may be used under the terms of the | |
27 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
28 | * case the provisions of LGPL are applicable instead of those above. If you | |
29 | * wish to allow use of your version of this file only under the terms of the | |
30 | * LGPL and not to allow others to use your version of this file under the | |
31 | * MPL, indicate your decision by deleting the provisions above and replace | |
32 | * them with the notice and other provisions required by the LGPL. If you do | |
33 | * not delete the provisions above, a recipient may use your version of this | |
34 | * file under either the MPL or the LGPL. | |
35 | */ | |
36 | ||
37 | #ifndef _TCP_BSD_H | |
38 | #define _TCP_BSD_H | |
39 | ||
40 | #include "socket.h" | |
41 | #include "agent.h" | |
42 | ||
43 | G_BEGIN_DECLS | |
44 | ||
45 | ||
46 | NiceSocket * | |
47 | nice_tcp_bsd_socket_new (NiceAgent *agent, GMainContext *ctx, NiceAddress *addr); | |
48 | ||
49 | ||
50 | G_END_DECLS | |
51 | ||
52 | #endif /* _TCP_BSD_H */ | |
53 |
57 | 57 | #endif |
58 | 58 | |
59 | 59 | typedef struct { |
60 | NiceUdpTurnSocketCompatibility compatibility; | |
61 | GQueue send_queue; | |
60 | NiceTurnSocketCompatibility compatibility; | |
62 | 61 | gchar recv_buf[65536]; |
63 | 62 | guint recv_buf_len; |
64 | 63 | guint expecting_len; |
65 | NiceAddress server_addr; | |
66 | GMainContext *context; | |
67 | GIOChannel *io_channel; | |
68 | GSource *io_source; | |
64 | NiceSocket *base_socket; | |
69 | 65 | } TurnTcpPriv; |
70 | 66 | |
71 | struct to_be_sent { | |
72 | guint length; | |
73 | gchar *buf; | |
74 | }; | |
75 | ||
76 | /*** NiceSocket ***/ | |
67 | ||
68 | static void socket_close (NiceSocket *sock); | |
69 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
70 | guint len, gchar *buf); | |
71 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
72 | guint len, const gchar *buf); | |
73 | static gboolean socket_is_reliable (NiceSocket *sock); | |
74 | ||
75 | NiceSocket * | |
76 | nice_tcp_turn_socket_new (NiceAgent *agent, NiceSocket *base_socket, | |
77 | NiceTurnSocketCompatibility compatibility) | |
78 | { | |
79 | TurnTcpPriv *priv; | |
80 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
81 | sock->priv = priv = g_slice_new0 (TurnTcpPriv); | |
82 | ||
83 | priv->compatibility = compatibility; | |
84 | priv->base_socket = base_socket; | |
85 | ||
86 | sock->fileno = priv->base_socket->fileno; | |
87 | sock->addr = priv->base_socket->addr; | |
88 | sock->send = socket_send; | |
89 | sock->recv = socket_recv; | |
90 | sock->is_reliable = socket_is_reliable; | |
91 | sock->close = socket_close; | |
92 | ||
93 | return sock; | |
94 | } | |
95 | ||
96 | ||
97 | static void | |
98 | socket_close (NiceSocket *sock) | |
99 | { | |
100 | TurnTcpPriv *priv = sock->priv; | |
101 | ||
102 | if (priv->base_socket) | |
103 | nice_socket_free (priv->base_socket); | |
104 | ||
105 | g_slice_free(TurnTcpPriv, sock->priv); | |
106 | } | |
107 | ||
77 | 108 | |
78 | 109 | static gint |
79 | socket_recv ( | |
80 | NiceSocket *sock, | |
81 | NiceAddress *from, | |
82 | guint len, | |
83 | gchar *buf) | |
110 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
84 | 111 | { |
85 | 112 | TurnTcpPriv *priv = sock->priv; |
86 | 113 | int ret; |
89 | 116 | if (priv->expecting_len == 0) { |
90 | 117 | guint headerlen = 0; |
91 | 118 | |
92 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
119 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
93 | 120 | headerlen = 4; |
94 | else if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) | |
121 | else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) | |
95 | 122 | headerlen = 2; |
96 | 123 | else |
97 | g_assert_not_reached(); | |
98 | ||
99 | ret = recv (sock->fileno, priv->recv_buf + priv->recv_buf_len, | |
100 | headerlen - priv->recv_buf_len, 0); | |
101 | if (ret < 0) { | |
102 | #ifdef G_OS_WIN32 | |
103 | if (WSAGetLastError () == WSAEWOULDBLOCK) | |
104 | #else | |
105 | if (errno == EAGAIN) | |
106 | #endif | |
107 | return 0; | |
108 | else | |
124 | return -1; | |
125 | ||
126 | ret = nice_socket_recv (priv->base_socket, from, | |
127 | headerlen - priv->recv_buf_len, priv->recv_buf + priv->recv_buf_len); | |
128 | if (ret < 0) | |
109 | 129 | return ret; |
110 | } | |
111 | 130 | |
112 | 131 | priv->recv_buf_len += ret; |
113 | 132 | |
114 | 133 | if (priv->recv_buf_len < headerlen) |
115 | 134 | return 0; |
116 | 135 | |
117 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
136 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
118 | 137 | guint16 magic = ntohs (*(guint16*)priv->recv_buf); |
119 | 138 | guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2)); |
120 | 139 | |
126 | 145 | priv->expecting_len = 4 + packetlen; |
127 | 146 | } |
128 | 147 | } |
129 | else if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
148 | else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
130 | 149 | guint len = ntohs (*(guint16*)priv->recv_buf); |
131 | 150 | priv->expecting_len = len; |
132 | 151 | priv->recv_buf_len = 0; |
133 | 152 | } |
134 | 153 | } |
135 | 154 | |
136 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
155 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
137 | 156 | padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0; |
138 | 157 | else |
139 | 158 | padlen = 0; |
140 | 159 | |
141 | ret = recv (sock->fileno, priv->recv_buf + priv->recv_buf_len, | |
142 | priv->expecting_len + padlen - priv->recv_buf_len, 0); | |
143 | if (ret < 0) { | |
144 | #ifdef G_OS_WIN32 | |
145 | if (WSAGetLastError () == WSAEWOULDBLOCK) | |
146 | #else | |
147 | if (errno == EAGAIN) | |
148 | #endif | |
149 | return 0; | |
150 | else | |
160 | ret = nice_socket_recv (priv->base_socket, from, | |
161 | priv->expecting_len + padlen - priv->recv_buf_len, | |
162 | priv->recv_buf + priv->recv_buf_len); | |
163 | ||
164 | if (ret < 0) | |
151 | 165 | return ret; |
152 | } | |
153 | 166 | |
154 | 167 | priv->recv_buf_len += ret; |
155 | 168 | |
158 | 171 | memcpy (buf, priv->recv_buf, copy_len); |
159 | 172 | priv->expecting_len = 0; |
160 | 173 | priv->recv_buf_len = 0; |
161 | if (from) | |
162 | *from = priv->server_addr; | |
174 | ||
163 | 175 | return copy_len; |
164 | 176 | } |
165 | 177 | |
166 | 178 | return 0; |
167 | 179 | } |
168 | static void | |
169 | add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head); | |
170 | ||
171 | ||
172 | ||
173 | /* | |
174 | * Returns: | |
175 | * -1 = error | |
176 | * 0 = have more to send | |
177 | * 1 = sent everything | |
178 | */ | |
179 | 180 | |
180 | 181 | static gboolean |
181 | socket_send_more ( | |
182 | GIOChannel *source, | |
183 | G_GNUC_UNUSED | |
184 | GIOCondition condition, | |
185 | gpointer data) | |
186 | { | |
187 | NiceSocket *sock = (NiceSocket *) data; | |
188 | TurnTcpPriv *priv = sock->priv; | |
189 | struct to_be_sent *tbs = NULL; | |
190 | ||
191 | while ((tbs = g_queue_pop_head (&priv->send_queue))) { | |
192 | int ret; | |
193 | ||
194 | ret = send (sock->fileno, tbs->buf, tbs->length, 0); | |
195 | ||
196 | if (ret < 0) { | |
197 | #ifdef G_OS_WIN32 | |
198 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
199 | #else | |
200 | if (errno == EAGAIN) { | |
201 | #endif | |
202 | add_to_be_sent (sock, tbs->buf, tbs->length, TRUE); | |
203 | g_free (tbs->buf); | |
204 | g_slice_free (struct to_be_sent, tbs); | |
205 | break; | |
206 | } | |
207 | } else if (ret < (int) tbs->length) { | |
208 | add_to_be_sent (sock, tbs->buf + ret, tbs->length - ret, TRUE); | |
209 | g_free (tbs->buf); | |
210 | g_slice_free (struct to_be_sent, tbs); | |
211 | break; | |
212 | } | |
213 | ||
214 | g_free (tbs->buf); | |
215 | g_slice_free (struct to_be_sent, tbs); | |
216 | } | |
217 | ||
218 | if (g_queue_is_empty (&priv->send_queue)) { | |
219 | g_io_channel_unref (priv->io_channel); | |
220 | priv->io_channel = NULL; | |
221 | g_source_destroy (priv->io_source); | |
222 | g_source_unref (priv->io_source); | |
223 | priv->io_source = NULL; | |
224 | return FALSE; | |
225 | } | |
226 | ||
227 | return TRUE; | |
228 | } | |
229 | ||
230 | ||
231 | static void | |
232 | add_to_be_sent (NiceSocket *sock, const gchar *buf, guint len, gboolean head) | |
233 | { | |
234 | TurnTcpPriv *priv = sock->priv; | |
235 | struct to_be_sent *tbs = g_slice_new (struct to_be_sent); | |
236 | ||
237 | if (len <= 0) | |
238 | return; | |
239 | ||
240 | tbs->buf = g_memdup (buf, len); | |
241 | tbs->length = len; | |
242 | if (head) | |
243 | g_queue_push_head (&priv->send_queue, tbs); | |
244 | else | |
245 | g_queue_push_tail (&priv->send_queue, tbs); | |
246 | ||
247 | if (priv->io_channel == NULL) { | |
248 | priv->io_channel = g_io_channel_unix_new (sock->fileno); | |
249 | priv->io_source = g_io_create_watch (priv->io_channel, G_IO_OUT); | |
250 | g_source_set_callback (priv->io_source, (GSourceFunc) socket_send_more, | |
251 | sock, NULL); | |
252 | g_source_attach (priv->io_source, priv->context); | |
253 | } | |
254 | } | |
255 | ||
256 | ||
257 | static gboolean | |
258 | socket_send ( | |
259 | NiceSocket *sock, | |
260 | const NiceAddress *to, | |
261 | guint len, | |
262 | const gchar *buf) | |
263 | { | |
264 | int ret; | |
182 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
183 | guint len, const gchar *buf) | |
184 | { | |
185 | gboolean ret = TRUE; | |
265 | 186 | TurnTcpPriv *priv = sock->priv; |
266 | 187 | gchar padbuf[3] = {0, 0, 0}; |
267 | 188 | int padlen = (len%4) ? 4 - (len%4) : 0; |
268 | 189 | |
269 | if (priv->compatibility != NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
190 | if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
270 | 191 | padlen = 0; |
271 | 192 | |
272 | /* First try to send the data, don't send it later if it can be sent now | |
273 | this way we avoid allocating memory on every send */ | |
274 | if (g_queue_is_empty (&priv->send_queue)) { | |
275 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
276 | guint16 tmpbuf = htons (len); | |
277 | ret = send (sock->fileno, (void *) &tmpbuf, sizeof(guint16), 0); | |
278 | ||
279 | if (ret < 0) { | |
280 | #ifdef G_OS_WIN32 | |
281 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
282 | #else | |
283 | if (errno == EAGAIN) { | |
284 | #endif | |
285 | add_to_be_sent (sock, (gchar *) &tmpbuf, sizeof(guint16), FALSE); | |
286 | add_to_be_sent (sock, buf, len, FALSE); | |
287 | return TRUE; | |
288 | } else { | |
289 | return FALSE; | |
290 | } | |
291 | } else if ((guint)ret < sizeof(guint16)) { | |
292 | add_to_be_sent (sock, ((gchar *) &tmpbuf) + ret, | |
293 | sizeof(guint16) - ret, FALSE); | |
294 | add_to_be_sent (sock, buf, len, FALSE); | |
295 | return TRUE; | |
296 | } | |
297 | } | |
298 | ||
299 | ret = send (sock->fileno, buf, len, 0); | |
300 | ||
301 | if (ret < 0) { | |
302 | #ifdef G_OS_WIN32 | |
303 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
304 | #else | |
305 | if (errno == EAGAIN) { | |
306 | #endif | |
307 | add_to_be_sent (sock, buf, len, FALSE); | |
308 | add_to_be_sent (sock, padbuf, padlen, FALSE); | |
309 | return TRUE; | |
310 | } else { | |
311 | return FALSE; | |
312 | } | |
313 | } else if ((guint)ret < len) { | |
314 | add_to_be_sent (sock, buf + ret, len - ret, FALSE); | |
315 | add_to_be_sent (sock, padbuf, padlen, FALSE); | |
316 | return TRUE; | |
317 | } | |
318 | ||
319 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9 && | |
320 | len % 4) { | |
321 | ||
322 | ret = send (sock->fileno, padbuf, padlen, 0); | |
323 | ||
324 | if (ret < 0) { | |
325 | #ifdef G_OS_WIN32 | |
326 | if (WSAGetLastError () == WSAEWOULDBLOCK) { | |
327 | #else | |
328 | if (errno == EAGAIN) { | |
329 | #endif | |
330 | add_to_be_sent (sock, padbuf, padlen, FALSE); | |
331 | return TRUE; | |
332 | } else { | |
333 | return FALSE; | |
334 | } | |
335 | } else if (ret < padlen) { | |
336 | add_to_be_sent (sock, padbuf, padlen - ret, FALSE); | |
337 | return TRUE; | |
338 | } | |
339 | } | |
340 | } else { | |
341 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
342 | guint16 tmpbuf = htons (len); | |
343 | add_to_be_sent (sock, (gchar*) &tmpbuf, sizeof(guint16), FALSE); | |
344 | } | |
345 | add_to_be_sent (sock, buf, len, FALSE); | |
346 | add_to_be_sent (sock, padbuf, padlen, FALSE); | |
193 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
194 | guint16 tmpbuf = htons (len); | |
195 | ret = nice_socket_send (priv->base_socket, to, | |
196 | sizeof(guint16), (gchar *)&tmpbuf); | |
197 | ||
198 | if (!ret) | |
199 | return ret; | |
347 | 200 | } |
348 | 201 | |
349 | return TRUE; | |
350 | } | |
351 | ||
352 | static void | |
353 | free_to_be_sent (struct to_be_sent *tbs) | |
354 | { | |
355 | g_free (tbs->buf); | |
356 | g_slice_free (struct to_be_sent, tbs); | |
357 | } | |
358 | ||
359 | static void | |
360 | socket_close (NiceSocket *sock) | |
361 | { | |
362 | TurnTcpPriv *priv = sock->priv; | |
363 | #ifdef G_OS_WIN32 | |
364 | closesocket(sock->fileno); | |
365 | #else | |
366 | close (sock->fileno); | |
367 | #endif | |
368 | g_queue_foreach (&priv->send_queue, (GFunc) free_to_be_sent, NULL); | |
369 | g_queue_clear (&priv->send_queue); | |
370 | if (priv->io_channel) | |
371 | g_io_channel_unref (priv->io_channel); | |
372 | if (priv->io_source) { | |
373 | g_source_destroy (priv->io_source); | |
374 | g_source_unref (priv->io_source); | |
375 | } | |
376 | g_slice_free(TurnTcpPriv, sock->priv); | |
377 | } | |
202 | ret = nice_socket_send (priv->base_socket, to, len, buf); | |
203 | ||
204 | if (!ret) | |
205 | return ret; | |
206 | ||
207 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) | |
208 | ret = nice_socket_send (priv->base_socket, to, padlen, padbuf); | |
209 | ||
210 | return ret; | |
211 | } | |
212 | ||
378 | 213 | |
379 | 214 | static gboolean |
380 | 215 | socket_is_reliable (NiceSocket *sock) |
382 | 217 | return TRUE; |
383 | 218 | } |
384 | 219 | |
385 | ||
386 | NiceSocket * | |
387 | nice_tcp_turn_socket_new ( | |
388 | NiceAgent *agent, | |
389 | GMainContext *ctx, | |
390 | NiceAddress *addr, | |
391 | NiceUdpTurnSocketCompatibility compatibility) | |
392 | { | |
393 | int sockfd = -1; | |
394 | int ret; | |
395 | struct sockaddr_storage name; | |
396 | guint name_len = sizeof (name); | |
397 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
398 | TurnTcpPriv *priv; | |
399 | ||
400 | if (addr != NULL) { | |
401 | nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); | |
402 | } else { | |
403 | memset (&name, 0, sizeof (name)); | |
404 | name.ss_family = AF_UNSPEC; | |
405 | } | |
406 | ||
407 | if ((sockfd == -1) && | |
408 | ((name.ss_family == AF_UNSPEC) || | |
409 | (name.ss_family == AF_INET))) { | |
410 | sockfd = socket (PF_INET, SOCK_STREAM, 0); | |
411 | name.ss_family = AF_INET; | |
412 | #ifdef HAVE_SA_LEN | |
413 | name.ss_len = sizeof (struct sockaddr_in); | |
414 | #endif | |
415 | } | |
416 | ||
417 | if (sockfd == -1) { | |
418 | g_slice_free (NiceSocket, sock); | |
419 | return NULL; | |
420 | } | |
421 | ||
422 | #ifdef FD_CLOEXEC | |
423 | fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC); | |
424 | #endif | |
425 | #ifdef O_NONBLOCK | |
426 | fcntl (sockfd, F_SETFL, fcntl (sockfd, F_GETFL) | O_NONBLOCK); | |
427 | #endif | |
428 | ||
429 | name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
430 | sizeof(struct sockaddr_in6); | |
431 | ret = connect (sockfd, (const struct sockaddr *)&name, name_len); | |
432 | ||
433 | #ifdef G_OS_WIN32 | |
434 | if (ret < 0 && WSAGetLastError () != WSAEINPROGRESS) { | |
435 | closesocket (sockfd); | |
436 | #else | |
437 | if (ret < 0 && errno != EINPROGRESS) { | |
438 | close (sockfd); | |
439 | #endif | |
440 | g_slice_free (NiceSocket, sock); | |
441 | return NULL; | |
442 | } | |
443 | ||
444 | name_len = name.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
445 | sizeof(struct sockaddr_in6); | |
446 | if (getsockname (sockfd, (struct sockaddr *) &name, &name_len) < 0) { | |
447 | g_slice_free (NiceSocket, sock); | |
448 | #ifdef G_OS_WIN32 | |
449 | closesocket(sockfd); | |
450 | #else | |
451 | close (sockfd); | |
452 | #endif | |
453 | return NULL; | |
454 | } | |
455 | ||
456 | nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name); | |
457 | ||
458 | sock->priv = priv = g_slice_new0 (TurnTcpPriv); | |
459 | ||
460 | priv->compatibility = compatibility; | |
461 | priv->server_addr = *addr; | |
462 | priv->context = ctx; | |
463 | ||
464 | sock->fileno = sockfd; | |
465 | sock->send = socket_send; | |
466 | sock->recv = socket_recv; | |
467 | sock->is_reliable = socket_is_reliable; | |
468 | sock->close = socket_close; | |
469 | ||
470 | return sock; | |
471 | } |
44 | 44 | |
45 | 45 | |
46 | 46 | NiceSocket * |
47 | nice_tcp_turn_socket_new ( | |
48 | NiceAgent *agent, | |
49 | GMainContext *ctx, | |
50 | NiceAddress *addr, | |
51 | NiceUdpTurnSocketCompatibility compatibility); | |
47 | nice_tcp_turn_socket_new (NiceAgent *agent, NiceSocket *base_socket, | |
48 | NiceTurnSocketCompatibility compatibility); | |
52 | 49 | |
53 | 50 | |
54 | 51 | G_END_DECLS |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * (C) 2008 Nokia Corporation | |
5 | * Contact: Youness Alaoui | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Dafydd Harries, Collabora Ltd. | |
24 | * Youness Alaoui, Collabora Ltd. | |
25 | * Rémi Denis-Courmont, Nokia | |
26 | * Kai Vehmanen | |
27 | * | |
28 | * Alternatively, the contents of this file may be used under the terms of the | |
29 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
30 | * case the provisions of LGPL are applicable instead of those above. If you | |
31 | * wish to allow use of your version of this file only under the terms of the | |
32 | * LGPL and not to allow others to use your version of this file under the | |
33 | * MPL, indicate your decision by deleting the provisions above and replace | |
34 | * them with the notice and other provisions required by the LGPL. If you do | |
35 | * not delete the provisions above, a recipient may use your version of this | |
36 | * file under either the MPL or the LGPL. | |
37 | */ | |
38 | ||
39 | /* | |
40 | * Implementation of TURN | |
41 | */ | |
42 | #ifdef HAVE_CONFIG_H | |
43 | # include "config.h" | |
44 | #endif | |
45 | ||
46 | #include <string.h> | |
47 | #include <errno.h> | |
48 | #include <fcntl.h> | |
49 | ||
50 | #include "turn.h" | |
51 | #include "stun/stunagent.h" | |
52 | #include "stun/usages/timer.h" | |
53 | #include "agent-priv.h" | |
54 | ||
55 | typedef struct { | |
56 | StunMessage message; | |
57 | uint8_t buffer[STUN_MAX_MESSAGE_SIZE]; | |
58 | stun_timer_t timer; | |
59 | } TURNMessage; | |
60 | ||
61 | ||
62 | typedef struct { | |
63 | NiceAddress peer; | |
64 | uint16_t channel; | |
65 | } ChannelBinding; | |
66 | ||
67 | typedef struct { | |
68 | NiceAgent *nice; | |
69 | StunAgent agent; | |
70 | GList *channels; | |
71 | GList *pending_bindings; | |
72 | ChannelBinding *current_binding; | |
73 | TURNMessage *current_binding_msg; | |
74 | GSource *tick_source; | |
75 | NiceSocket *base_socket; | |
76 | NiceAddress server_addr; | |
77 | uint8_t *username; | |
78 | size_t username_len; | |
79 | uint8_t *password; | |
80 | size_t password_len; | |
81 | NiceTurnSocketCompatibility compatibility; | |
82 | } TurnPriv; | |
83 | ||
84 | ||
85 | ||
86 | static void socket_close (NiceSocket *sock); | |
87 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
88 | guint len, gchar *buf); | |
89 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
90 | guint len, const gchar *buf); | |
91 | static gboolean socket_is_reliable (NiceSocket *sock); | |
92 | ||
93 | static void priv_process_pending_bindings (TurnPriv *priv); | |
94 | static gboolean priv_retransmissions_tick_unlocked (TurnPriv *priv); | |
95 | static gboolean priv_retransmissions_tick (gpointer pointer); | |
96 | static void priv_schedule_tick (TurnPriv *priv); | |
97 | static void priv_send_turn_message (TurnPriv *priv, TURNMessage *msg); | |
98 | static gboolean priv_send_channel_bind (TurnPriv *priv, StunMessage *resp, | |
99 | uint16_t channel, NiceAddress *peer); | |
100 | static gboolean priv_add_channel_binding (TurnPriv *priv, NiceAddress *peer); | |
101 | ||
102 | ||
103 | ||
104 | NiceSocket * | |
105 | nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr, | |
106 | NiceSocket *base_socket, NiceAddress *server_addr, | |
107 | gchar *username, gchar *password, NiceTurnSocketCompatibility compatibility) | |
108 | { | |
109 | TurnPriv *priv = g_new0 (TurnPriv, 1); | |
110 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
111 | ||
112 | if (!sock) { | |
113 | return NULL; | |
114 | } | |
115 | ||
116 | if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
117 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
118 | STUN_COMPATIBILITY_RFC5389, | |
119 | STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS); | |
120 | } else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN) { | |
121 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
122 | STUN_COMPATIBILITY_RFC3489, | |
123 | STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | | |
124 | STUN_AGENT_USAGE_NO_INDICATION_AUTH); | |
125 | } else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
126 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
127 | STUN_COMPATIBILITY_RFC3489, | |
128 | STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | | |
129 | STUN_AGENT_USAGE_IGNORE_CREDENTIALS); | |
130 | } | |
131 | ||
132 | priv->nice = agent; | |
133 | priv->channels = NULL; | |
134 | priv->current_binding = NULL; | |
135 | priv->base_socket = base_socket; | |
136 | ||
137 | if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN) { | |
138 | priv->username = g_base64_decode (username, &priv->username_len); | |
139 | priv->password = g_base64_decode (password, &priv->password_len); | |
140 | } else { | |
141 | priv->username = (uint8_t *)g_strdup (username); | |
142 | priv->username_len = (size_t) strlen (username); | |
143 | if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
144 | priv->password = NULL; | |
145 | priv->password_len = 0; | |
146 | } else { | |
147 | priv->password = (uint8_t *)g_strdup (password); | |
148 | priv->password_len = (size_t) strlen (password); | |
149 | } | |
150 | } | |
151 | priv->server_addr = *server_addr; | |
152 | priv->compatibility = compatibility; | |
153 | sock->addr = *addr; | |
154 | sock->fileno = base_socket->fileno; | |
155 | sock->send = socket_send; | |
156 | sock->recv = socket_recv; | |
157 | sock->is_reliable = socket_is_reliable; | |
158 | sock->close = socket_close; | |
159 | sock->priv = (void *) priv; | |
160 | return sock; | |
161 | } | |
162 | ||
163 | ||
164 | static void | |
165 | socket_close (NiceSocket *sock) | |
166 | { | |
167 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
168 | GList *i = NULL; | |
169 | for (i = priv->channels; i; i = i->next) { | |
170 | ChannelBinding *b = i->data; | |
171 | g_free (b); | |
172 | } | |
173 | g_list_free (priv->channels); | |
174 | ||
175 | for (i = priv->pending_bindings; i; i = i->next) { | |
176 | ChannelBinding *b = i->data; | |
177 | g_free (b); | |
178 | } | |
179 | g_list_free (priv->pending_bindings); | |
180 | ||
181 | if (priv->tick_source != NULL) { | |
182 | g_source_destroy (priv->tick_source); | |
183 | g_source_unref (priv->tick_source); | |
184 | priv->tick_source = NULL; | |
185 | } | |
186 | ||
187 | g_free (priv->current_binding); | |
188 | g_free (priv->current_binding_msg); | |
189 | g_free (priv->username); | |
190 | g_free (priv->password); | |
191 | g_free (priv); | |
192 | } | |
193 | ||
194 | static gint | |
195 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
196 | { | |
197 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
198 | uint8_t recv_buf[STUN_MAX_MESSAGE_SIZE]; | |
199 | gint recv_len; | |
200 | NiceAddress recv_from; | |
201 | NiceSocket *dummy;; | |
202 | ||
203 | recv_len = nice_socket_recv (priv->base_socket, &recv_from, | |
204 | sizeof(recv_buf), (gchar *) recv_buf); | |
205 | ||
206 | return nice_turn_socket_parse_recv (sock, &dummy, from, len, buf, | |
207 | &recv_from, (gchar *) recv_buf, (guint) recv_len); | |
208 | } | |
209 | ||
210 | static gboolean | |
211 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
212 | guint len, const gchar *buf) | |
213 | { | |
214 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
215 | StunMessage msg; | |
216 | uint8_t buffer[STUN_MAX_MESSAGE_SIZE]; | |
217 | size_t msg_len; | |
218 | struct sockaddr_storage sa; | |
219 | GList *i = priv->channels; | |
220 | ChannelBinding *binding = NULL; | |
221 | ||
222 | for (; i; i = i->next) { | |
223 | ChannelBinding *b = i->data; | |
224 | if (nice_address_equal (&b->peer, to)) { | |
225 | binding = b; | |
226 | break; | |
227 | } | |
228 | } | |
229 | ||
230 | nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); | |
231 | ||
232 | if (binding) { | |
233 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 && | |
234 | len + sizeof(uint32_t) <= sizeof(buffer)) { | |
235 | uint16_t len16 = htons ((uint16_t) len); | |
236 | uint16_t channel16 = htons (binding->channel); | |
237 | memcpy (buffer, &channel16, sizeof(uint16_t)); | |
238 | memcpy (buffer + sizeof(uint16_t), &len16,sizeof(uint16_t)); | |
239 | memcpy (buffer + sizeof(uint32_t), buf, len); | |
240 | msg_len = len + sizeof(uint32_t); | |
241 | } else { | |
242 | return nice_socket_send (priv->base_socket, &priv->server_addr, len, buf); | |
243 | } | |
244 | } else { | |
245 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
246 | if (!stun_agent_init_indication (&priv->agent, &msg, | |
247 | buffer, sizeof(buffer), STUN_IND_SEND)) | |
248 | goto send; | |
249 | if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_PEER_ADDRESS, | |
250 | (struct sockaddr *)&sa, sizeof(sa)) != 0) | |
251 | goto send; | |
252 | } else { | |
253 | if (!stun_agent_init_request (&priv->agent, &msg, | |
254 | buffer, sizeof(buffer), STUN_SEND)) | |
255 | goto send; | |
256 | ||
257 | if (stun_message_append32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
258 | TURN_MAGIC_COOKIE) != 0) | |
259 | goto send; | |
260 | if (priv->username != NULL && priv->username_len > 0) { | |
261 | if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_USERNAME, | |
262 | priv->username, priv->username_len) != 0) | |
263 | goto send; | |
264 | } | |
265 | if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_DESTINATION_ADDRESS, | |
266 | (struct sockaddr *)&sa, sizeof(sa)) != 0) | |
267 | goto send; | |
268 | ||
269 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE && | |
270 | priv->current_binding && | |
271 | nice_address_equal (&priv->current_binding->peer, to)) { | |
272 | stun_message_append32 (&msg, STUN_ATTRIBUTE_OPTIONS, 1); | |
273 | } | |
274 | } | |
275 | ||
276 | if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_DATA, buf, len) != 0) | |
277 | goto send; | |
278 | ||
279 | msg_len = stun_agent_finish_message (&priv->agent, &msg, | |
280 | priv->password, priv->password_len); | |
281 | } | |
282 | ||
283 | if (msg_len > 0) { | |
284 | return nice_socket_send (priv->base_socket, &priv->server_addr, | |
285 | msg_len, (gchar *)buffer); | |
286 | } | |
287 | send: | |
288 | return nice_socket_send (priv->base_socket, to, len, buf); | |
289 | } | |
290 | ||
291 | static gboolean | |
292 | socket_is_reliable (NiceSocket *sock) | |
293 | { | |
294 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
295 | return nice_socket_is_reliable (priv->base_socket); | |
296 | } | |
297 | ||
298 | ||
299 | ||
300 | gint | |
301 | nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, | |
302 | NiceAddress *from, guint len, gchar *buf, | |
303 | NiceAddress *recv_from, gchar *recv_buf, guint recv_len) | |
304 | { | |
305 | ||
306 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
307 | StunValidationStatus valid; | |
308 | StunMessage msg; | |
309 | struct sockaddr_storage sa; | |
310 | socklen_t from_len = sizeof (sa); | |
311 | GList *i = priv->channels; | |
312 | ChannelBinding *binding = NULL; | |
313 | ||
314 | if (nice_address_equal (&priv->server_addr, recv_from)) { | |
315 | valid = stun_agent_validate (&priv->agent, &msg, | |
316 | (uint8_t *) recv_buf, (size_t) recv_len, NULL, NULL); | |
317 | ||
318 | if (valid == STUN_VALIDATION_SUCCESS) { | |
319 | if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
320 | uint32_t cookie; | |
321 | if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
322 | &cookie) != 0) | |
323 | goto recv; | |
324 | if (cookie != TURN_MAGIC_COOKIE) | |
325 | goto recv; | |
326 | } | |
327 | ||
328 | if (stun_message_get_method (&msg) == STUN_SEND) { | |
329 | if (stun_message_get_class (&msg) == STUN_RESPONSE && | |
330 | priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
331 | uint32_t opts = 0; | |
332 | if (stun_message_find32 (&msg, STUN_ATTRIBUTE_OPTIONS, &opts) == 0 && | |
333 | opts & 0x1) | |
334 | goto msn_google_lock; | |
335 | } | |
336 | return 0; | |
337 | } else if (stun_message_get_method (&msg) == STUN_OLD_SET_ACTIVE_DST) { | |
338 | stun_transid_t request_id; | |
339 | stun_transid_t response_id; | |
340 | if (priv->current_binding && priv->current_binding_msg) { | |
341 | stun_message_id (&msg, response_id); | |
342 | stun_message_id (&priv->current_binding_msg->message, request_id); | |
343 | if (memcmp (request_id, response_id, sizeof(stun_transid_t)) == 0) { | |
344 | g_free (priv->current_binding_msg); | |
345 | priv->current_binding_msg = NULL; | |
346 | ||
347 | if (stun_message_get_class (&msg) == STUN_RESPONSE && | |
348 | priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN) { | |
349 | goto msn_google_lock; | |
350 | } else { | |
351 | g_free (priv->current_binding); | |
352 | priv->current_binding = NULL; | |
353 | } | |
354 | } | |
355 | } | |
356 | ||
357 | return 0; | |
358 | } else if (stun_message_get_method (&msg) == STUN_CHANNELBIND) { | |
359 | stun_transid_t request_id; | |
360 | stun_transid_t response_id; | |
361 | if (priv->current_binding && priv->current_binding_msg) { | |
362 | stun_message_id (&msg, response_id); | |
363 | stun_message_id (&priv->current_binding_msg->message, request_id); | |
364 | if (memcmp (request_id, response_id, sizeof(stun_transid_t)) == 0) { | |
365 | if (stun_message_get_class (&msg) == STUN_ERROR) { | |
366 | int code = -1; | |
367 | uint8_t *sent_realm = NULL; | |
368 | uint8_t *recv_realm = NULL; | |
369 | uint16_t sent_realm_len = 0; | |
370 | uint16_t recv_realm_len = 0; | |
371 | ||
372 | sent_realm = (uint8_t *) stun_message_find ( | |
373 | &priv->current_binding_msg->message, | |
374 | STUN_ATTRIBUTE_REALM, &sent_realm_len); | |
375 | recv_realm = (uint8_t *) stun_message_find (&msg, | |
376 | STUN_ATTRIBUTE_REALM, &recv_realm_len); | |
377 | ||
378 | /* check for unauthorized error response */ | |
379 | if (stun_message_find_error (&msg, &code) == 0 && | |
380 | (code == 438 || (code == 401 && | |
381 | !(recv_realm != NULL && | |
382 | recv_realm_len > 0 && | |
383 | recv_realm_len == sent_realm_len && | |
384 | sent_realm != NULL && | |
385 | memcmp (sent_realm, recv_realm, sent_realm_len) == 0)))) { | |
386 | g_free (priv->current_binding_msg); | |
387 | priv->current_binding_msg = NULL; | |
388 | if (priv->current_binding) { | |
389 | priv_send_channel_bind (priv, &msg, | |
390 | priv->current_binding->channel, | |
391 | &priv->current_binding->peer); | |
392 | } | |
393 | } else { | |
394 | g_free (priv->current_binding); | |
395 | priv->current_binding = NULL; | |
396 | g_free (priv->current_binding_msg); | |
397 | priv->current_binding_msg = NULL; | |
398 | priv_process_pending_bindings (priv); | |
399 | } | |
400 | } else if (stun_message_get_class (&msg) == STUN_RESPONSE) { | |
401 | g_free (priv->current_binding_msg); | |
402 | priv->current_binding_msg = NULL; | |
403 | if (priv->current_binding) { | |
404 | priv->channels = g_list_append (priv->channels, | |
405 | priv->current_binding); | |
406 | priv->current_binding = NULL; | |
407 | } | |
408 | priv_process_pending_bindings (priv); | |
409 | } | |
410 | } | |
411 | } | |
412 | return 0; | |
413 | } else if (stun_message_get_class (&msg) == STUN_INDICATION && | |
414 | stun_message_get_method (&msg) == STUN_IND_DATA) { | |
415 | uint16_t data_len; | |
416 | uint8_t *data; | |
417 | ||
418 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
419 | if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS, | |
420 | (struct sockaddr *)&sa, &from_len) != 0) | |
421 | goto recv; | |
422 | } else { | |
423 | if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS, | |
424 | (struct sockaddr *)&sa, &from_len) != 0) | |
425 | goto recv; | |
426 | } | |
427 | ||
428 | data = (uint8_t *) stun_message_find (&msg, STUN_ATTRIBUTE_DATA, | |
429 | &data_len); | |
430 | ||
431 | if (data == NULL) | |
432 | goto recv; | |
433 | ||
434 | nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); | |
435 | ||
436 | *from_sock = sock; | |
437 | memmove (buf, data, len > data_len ? data_len : len); | |
438 | return len > data_len ? data_len : len; | |
439 | } else { | |
440 | goto recv; | |
441 | } | |
442 | } | |
443 | } | |
444 | ||
445 | recv: | |
446 | for (i = priv->channels; i; i = i->next) { | |
447 | ChannelBinding *b = i->data; | |
448 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
449 | if (b->channel == ntohs(((uint16_t *)recv_buf)[0])) { | |
450 | recv_len = ntohs (((uint16_t *)recv_buf)[1]); | |
451 | recv_buf += sizeof(uint32_t); | |
452 | binding = b; | |
453 | break; | |
454 | } | |
455 | } else { | |
456 | binding = b; | |
457 | break; | |
458 | } | |
459 | } | |
460 | ||
461 | if (binding) { | |
462 | *from = binding->peer; | |
463 | *from_sock = sock; | |
464 | } else { | |
465 | *from = *recv_from; | |
466 | } | |
467 | ||
468 | memmove (buf, recv_buf, len > recv_len ? recv_len : len); | |
469 | return len > recv_len ? recv_len : len; | |
470 | ||
471 | msn_google_lock: | |
472 | ||
473 | if (priv->current_binding) { | |
474 | GList *i = priv->channels; | |
475 | for (; i; i = i->next) { | |
476 | ChannelBinding *b = i->data; | |
477 | g_free (b); | |
478 | } | |
479 | g_list_free (priv->channels); | |
480 | priv->channels = g_list_append (NULL, priv->current_binding); | |
481 | priv->current_binding = NULL; | |
482 | priv_process_pending_bindings (priv); | |
483 | } | |
484 | ||
485 | return 0; | |
486 | } | |
487 | ||
488 | gboolean | |
489 | nice_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer) | |
490 | { | |
491 | TurnPriv *priv = (TurnPriv *) sock->priv; | |
492 | return priv_add_channel_binding (priv, peer); | |
493 | } | |
494 | ||
495 | static void | |
496 | priv_process_pending_bindings (TurnPriv *priv) | |
497 | { | |
498 | gboolean ret = FALSE; | |
499 | while (priv->pending_bindings != NULL && ret == FALSE) { | |
500 | NiceAddress *peer = priv->pending_bindings->data; | |
501 | ret = priv_add_channel_binding (priv, peer); | |
502 | priv->pending_bindings = g_list_remove (priv->pending_bindings, peer); | |
503 | nice_address_free (peer); | |
504 | } | |
505 | } | |
506 | ||
507 | static gboolean | |
508 | priv_retransmissions_tick_unlocked (TurnPriv *priv) | |
509 | { | |
510 | if (priv->current_binding_msg) { | |
511 | guint timeout = stun_timer_refresh (&priv->current_binding_msg->timer); | |
512 | switch (timeout) { | |
513 | case -1: | |
514 | /* Time out */ | |
515 | g_free (priv->current_binding); | |
516 | priv->current_binding = NULL; | |
517 | g_free (priv->current_binding_msg); | |
518 | priv->current_binding_msg = NULL; | |
519 | priv_process_pending_bindings (priv); | |
520 | break; | |
521 | case 0: | |
522 | /* Retransmit */ | |
523 | nice_socket_send (priv->base_socket, &priv->server_addr, | |
524 | stun_message_length (&priv->current_binding_msg->message), | |
525 | (gchar *)priv->current_binding_msg->buffer); | |
526 | break; | |
527 | default: | |
528 | break; | |
529 | } | |
530 | } | |
531 | ||
532 | priv_schedule_tick (priv); | |
533 | return FALSE; | |
534 | } | |
535 | ||
536 | ||
537 | static gboolean | |
538 | priv_retransmissions_tick (gpointer pointer) | |
539 | { | |
540 | TurnPriv *priv = pointer; | |
541 | gboolean ret; | |
542 | ||
543 | g_static_rec_mutex_lock (&priv->nice->mutex); | |
544 | ret = priv_retransmissions_tick_unlocked (priv); | |
545 | g_static_rec_mutex_unlock (&priv->nice->mutex); | |
546 | ||
547 | return ret; | |
548 | } | |
549 | ||
550 | static void | |
551 | priv_schedule_tick (TurnPriv *priv) | |
552 | { | |
553 | if (priv->tick_source != NULL) { | |
554 | g_source_destroy (priv->tick_source); | |
555 | g_source_unref (priv->tick_source); | |
556 | priv->tick_source = NULL; | |
557 | } | |
558 | ||
559 | if (priv->current_binding_msg) { | |
560 | guint timeout = stun_timer_remainder (&priv->current_binding_msg->timer); | |
561 | if (timeout > 0) { | |
562 | priv->tick_source = agent_timeout_add_with_context (priv->nice, timeout, | |
563 | priv_retransmissions_tick, priv); | |
564 | } else { | |
565 | priv_retransmissions_tick_unlocked (priv); | |
566 | } | |
567 | } | |
568 | } | |
569 | ||
570 | static void | |
571 | priv_send_turn_message (TurnPriv *priv, TURNMessage *msg) | |
572 | { | |
573 | size_t stun_len = stun_message_length (&msg->message); | |
574 | ||
575 | if (priv->current_binding_msg) { | |
576 | g_free (priv->current_binding_msg); | |
577 | priv->current_binding_msg = NULL; | |
578 | } | |
579 | ||
580 | nice_socket_send (priv->base_socket, &priv->server_addr, | |
581 | stun_len, (gchar *)msg->buffer); | |
582 | ||
583 | if (nice_socket_is_reliable (priv->base_socket)) { | |
584 | stun_timer_start_reliable (&msg->timer); | |
585 | } else { | |
586 | stun_timer_start (&msg->timer); | |
587 | } | |
588 | ||
589 | priv->current_binding_msg = msg; | |
590 | priv_schedule_tick (priv); | |
591 | } | |
592 | ||
593 | static gboolean | |
594 | priv_send_channel_bind (TurnPriv *priv, StunMessage *resp, | |
595 | uint16_t channel, NiceAddress *peer) | |
596 | { | |
597 | uint32_t channel_attr = channel << 16; | |
598 | size_t stun_len; | |
599 | struct sockaddr_storage sa; | |
600 | TURNMessage *msg = g_new0 (TURNMessage, 1); | |
601 | ||
602 | nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa); | |
603 | ||
604 | if (!stun_agent_init_request (&priv->agent, &msg->message, | |
605 | msg->buffer, sizeof(msg->buffer), STUN_CHANNELBIND)) { | |
606 | g_free (msg); | |
607 | return FALSE; | |
608 | } | |
609 | ||
610 | if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_CHANNEL_NUMBER, | |
611 | channel_attr) != 0) { | |
612 | g_free (msg); | |
613 | return FALSE; | |
614 | } | |
615 | ||
616 | if (stun_message_append_xor_addr (&msg->message, STUN_ATTRIBUTE_PEER_ADDRESS, | |
617 | (struct sockaddr *)&sa, sizeof(sa)) != 0) { | |
618 | g_free (msg); | |
619 | return FALSE; | |
620 | } | |
621 | ||
622 | if (priv->username != NULL && priv->username_len > 0) { | |
623 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME, | |
624 | priv->username, priv->username_len) != 0) { | |
625 | g_free (msg); | |
626 | return FALSE; | |
627 | } | |
628 | } | |
629 | ||
630 | if (resp) { | |
631 | uint8_t *realm; | |
632 | uint8_t *nonce; | |
633 | uint16_t len; | |
634 | ||
635 | realm = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_REALM, &len); | |
636 | if (realm != NULL) { | |
637 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM, | |
638 | realm, len) != 0) { | |
639 | g_free (msg); | |
640 | return 0; | |
641 | } | |
642 | } | |
643 | nonce = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_NONCE, &len); | |
644 | if (nonce != NULL) { | |
645 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE, | |
646 | nonce, len) != 0) { | |
647 | g_free (msg); | |
648 | return 0; | |
649 | } | |
650 | } | |
651 | } | |
652 | ||
653 | stun_len = stun_agent_finish_message (&priv->agent, &msg->message, | |
654 | priv->password, priv->password_len); | |
655 | ||
656 | if (stun_len > 0) { | |
657 | priv_send_turn_message (priv, msg); | |
658 | return TRUE; | |
659 | } | |
660 | ||
661 | g_free (msg); | |
662 | return FALSE; | |
663 | } | |
664 | ||
665 | static gboolean | |
666 | priv_add_channel_binding (TurnPriv *priv, NiceAddress *peer) | |
667 | { | |
668 | size_t stun_len; | |
669 | struct sockaddr_storage sa; | |
670 | ||
671 | nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa); | |
672 | ||
673 | if (priv->current_binding) { | |
674 | NiceAddress * pending= nice_address_new (); | |
675 | *pending = *peer; | |
676 | priv->pending_bindings = g_list_append (priv->pending_bindings, pending); | |
677 | return FALSE; | |
678 | } | |
679 | ||
680 | if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
681 | uint16_t channel = 0x4000; | |
682 | GList *i = priv->channels; | |
683 | for (; i; i = i->next) { | |
684 | ChannelBinding *b = i->data; | |
685 | if (channel == b->channel) { | |
686 | i = priv->channels; | |
687 | channel++; | |
688 | continue; | |
689 | } | |
690 | } | |
691 | ||
692 | if (channel >= 0x4000 && channel < 0xffff) { | |
693 | gboolean ret = priv_send_channel_bind (priv, NULL, channel, peer); | |
694 | if (ret) { | |
695 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
696 | priv->current_binding->channel = channel; | |
697 | priv->current_binding->peer = *peer; | |
698 | } | |
699 | return ret; | |
700 | } | |
701 | return FALSE; | |
702 | } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN) { | |
703 | TURNMessage *msg = g_new0 (TURNMessage, 1); | |
704 | if (!stun_agent_init_request (&priv->agent, &msg->message, | |
705 | msg->buffer, sizeof(msg->buffer), STUN_OLD_SET_ACTIVE_DST)) { | |
706 | g_free (msg); | |
707 | return FALSE; | |
708 | } | |
709 | ||
710 | if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
711 | TURN_MAGIC_COOKIE) != 0) { | |
712 | g_free (msg); | |
713 | return FALSE; | |
714 | } | |
715 | ||
716 | if (priv->username != NULL && priv->username_len > 0) { | |
717 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME, | |
718 | priv->username, priv->username_len) != 0) { | |
719 | g_free (msg); | |
720 | return FALSE; | |
721 | } | |
722 | } | |
723 | ||
724 | if (stun_message_append_addr (&msg->message, | |
725 | STUN_ATTRIBUTE_DESTINATION_ADDRESS, | |
726 | (struct sockaddr *)&sa, sizeof(sa)) != 0) { | |
727 | g_free (msg); | |
728 | return FALSE; | |
729 | } | |
730 | ||
731 | stun_len = stun_agent_finish_message (&priv->agent, &msg->message, | |
732 | priv->password, priv->password_len); | |
733 | ||
734 | if (stun_len > 0) { | |
735 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
736 | priv->current_binding->channel = 0; | |
737 | priv->current_binding->peer = *peer; | |
738 | priv_send_turn_message (priv, msg); | |
739 | return TRUE; | |
740 | } | |
741 | g_free (msg); | |
742 | return FALSE; | |
743 | } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
744 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
745 | priv->current_binding->channel = 0; | |
746 | priv->current_binding->peer = *peer; | |
747 | return TRUE; | |
748 | } else { | |
749 | return FALSE; | |
750 | } | |
751 | ||
752 | return FALSE; | |
753 | } |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * (C) 2008 Nokia Corporation | |
5 | * Contact: Youness Alaoui | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Dafydd Harries, Collabora Ltd. | |
24 | * Youness Alaoui, Collabora Ltd. | |
25 | * | |
26 | * Alternatively, the contents of this file may be used under the terms of the | |
27 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
28 | * case the provisions of LGPL are applicable instead of those above. If you | |
29 | * wish to allow use of your version of this file only under the terms of the | |
30 | * LGPL and not to allow others to use your version of this file under the | |
31 | * MPL, indicate your decision by deleting the provisions above and replace | |
32 | * them with the notice and other provisions required by the LGPL. If you do | |
33 | * not delete the provisions above, a recipient may use your version of this | |
34 | * file under either the MPL or the LGPL. | |
35 | */ | |
36 | ||
37 | #ifndef _TURN_H | |
38 | #define _TURN_H | |
39 | ||
40 | ||
41 | typedef enum { | |
42 | NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9, | |
43 | NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE, | |
44 | NICE_TURN_SOCKET_COMPATIBILITY_MSN, | |
45 | } NiceTurnSocketCompatibility; | |
46 | ||
47 | #include "socket.h" | |
48 | #include "agent.h" | |
49 | ||
50 | ||
51 | G_BEGIN_DECLS | |
52 | ||
53 | gint | |
54 | nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock, | |
55 | NiceAddress *from, guint len, gchar *buf, | |
56 | NiceAddress *recv_from, gchar *recv_buf, guint recv_len); | |
57 | ||
58 | gboolean | |
59 | nice_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer); | |
60 | ||
61 | NiceSocket * | |
62 | nice_turn_socket_new (NiceAgent *agent, NiceAddress *addr, | |
63 | NiceSocket *base_socket, NiceAddress *server_addr, | |
64 | gchar *username, gchar *password, NiceTurnSocketCompatibility compatibility); | |
65 | ||
66 | ||
67 | G_END_DECLS | |
68 | ||
69 | #endif /* _TURN_H */ | |
70 |
57 | 57 | #include <unistd.h> |
58 | 58 | #endif |
59 | 59 | |
60 | /*** NiceSocket ***/ | |
61 | static int sock_recv_err (int fd) | |
62 | { | |
63 | #ifdef MSG_ERRQUEUE | |
64 | /* Silently dequeue any error message if any */ | |
65 | struct msghdr hdr; | |
66 | int saved = errno, val; | |
67 | 60 | |
68 | memset (&hdr, 0, sizeof (hdr)); | |
69 | val = recvmsg (fd, &hdr, MSG_ERRQUEUE); | |
70 | errno = saved; | |
71 | return val == 0; | |
72 | #else | |
73 | return 0; | |
74 | #endif | |
75 | } | |
76 | ||
77 | ||
78 | static gint | |
79 | socket_recv ( | |
80 | NiceSocket *sock, | |
81 | NiceAddress *from, | |
82 | guint len, | |
83 | gchar *buf) | |
84 | { | |
85 | gint recvd; | |
86 | struct sockaddr_storage sa; | |
87 | socklen_t from_len = sizeof (sa); | |
88 | ||
89 | recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa, | |
90 | &from_len); | |
91 | if (recvd == -1) | |
92 | { | |
93 | sock_recv_err (sock->fileno); | |
94 | return -1; | |
95 | } | |
96 | ||
97 | nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); | |
98 | return recvd; | |
99 | } | |
100 | ||
101 | static gboolean | |
102 | socket_send ( | |
103 | NiceSocket *sock, | |
104 | const NiceAddress *to, | |
105 | guint len, | |
106 | const gchar *buf) | |
107 | { | |
108 | struct sockaddr_storage sa; | |
109 | ssize_t sent; | |
110 | ||
111 | nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); | |
112 | ||
113 | do | |
114 | sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa, | |
115 | sa.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
116 | sizeof(struct sockaddr_in6)); | |
117 | while ((sent == -1) && sock_recv_err (sock->fileno)); | |
118 | ||
119 | return sent == (ssize_t)len; | |
120 | } | |
121 | ||
122 | static gboolean | |
123 | socket_is_reliable (NiceSocket *sock) | |
124 | { | |
125 | return FALSE; | |
126 | } | |
127 | ||
128 | static void | |
129 | socket_close (NiceSocket *sock) | |
130 | { | |
131 | #ifdef G_OS_WIN32 | |
132 | closesocket(sock->fileno); | |
133 | #else | |
134 | close (sock->fileno); | |
135 | #endif | |
136 | } | |
137 | ||
61 | static void socket_close (NiceSocket *sock); | |
62 | static gint socket_recv (NiceSocket *sock, NiceAddress *from, | |
63 | guint len, gchar *buf); | |
64 | static gboolean socket_send (NiceSocket *sock, const NiceAddress *to, | |
65 | guint len, const gchar *buf); | |
66 | static gboolean socket_is_reliable (NiceSocket *sock); | |
138 | 67 | |
139 | 68 | NiceSocket * |
140 | 69 | nice_udp_bsd_socket_new (NiceAddress *addr) |
148 | 77 | return NULL; |
149 | 78 | } |
150 | 79 | |
151 | if (addr != NULL) | |
152 | { | |
153 | nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); | |
154 | } | |
155 | else | |
156 | { | |
157 | memset (&name, 0, sizeof (name)); | |
158 | name.ss_family = AF_UNSPEC; | |
159 | } | |
80 | if (addr != NULL) { | |
81 | nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); | |
82 | } else { | |
83 | memset (&name, 0, sizeof (name)); | |
84 | name.ss_family = AF_UNSPEC; | |
85 | } | |
160 | 86 | |
161 | #if 0 | |
162 | if ((name.ss_family == AF_INET6) || (name.ss_family == AF_UNSPEC)) | |
163 | { | |
164 | sockfd = socket (PF_INET6, SOCK_DGRAM, 0); | |
165 | if (sockfd != -1) | |
166 | { | |
167 | int v6 = name.ss_family == AF_INET6; | |
168 | ||
169 | #if defined (IPV6_V6ONLY) | |
170 | if (setsockopt (sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &v6, sizeof (v6))) | |
171 | #else | |
172 | if (!v6) | |
87 | if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) { | |
88 | sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
89 | name.ss_family = AF_INET; | |
90 | #ifdef HAVE_SA_LEN | |
91 | name.ss_len = sizeof (struct sockaddr_in); | |
173 | 92 | #endif |
174 | { | |
175 | #ifdef G_OS_WIN32 | |
176 | closesocket(sock->fileno); | |
177 | #else | |
178 | close (sockfd); | |
179 | #endif | |
180 | sockfd = -1; | |
181 | } | |
182 | else | |
183 | { | |
184 | # ifdef IPV6_RECVERR | |
185 | int yes = 1; | |
186 | setsockopt (sockfd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes)); | |
187 | # endif | |
188 | name.ss_family = AF_INET6; | |
189 | # ifdef HAVE_SA_LEN | |
190 | name.ss_len = sizeof (struct sockaddr_in6); | |
191 | # endif | |
192 | } | |
193 | } | |
194 | } | |
195 | #endif | |
196 | if ((sockfd == -1) | |
197 | && ((name.ss_family == AF_UNSPEC) || (name.ss_family == AF_INET))) | |
198 | { | |
199 | sockfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
200 | name.ss_family = AF_INET; | |
201 | #ifdef HAVE_SA_LEN | |
202 | name.ss_len = sizeof (struct sockaddr_in); | |
203 | #endif | |
204 | } | |
93 | } | |
205 | 94 | |
206 | 95 | if (sockfd == -1) { |
207 | 96 | g_slice_free (NiceSocket, sock); |
208 | 97 | return NULL; |
209 | 98 | } |
210 | ||
211 | #ifdef IP_RECVERR | |
212 | else | |
213 | { | |
214 | int yes = 1; | |
215 | setsockopt (sockfd, SOL_IP, IP_RECVERR, &yes, sizeof (yes)); | |
216 | } | |
217 | #endif | |
218 | 99 | |
219 | 100 | #ifdef FD_CLOEXEC |
220 | 101 | fcntl (sockfd, F_SETFD, fcntl (sockfd, F_GETFD) | FD_CLOEXEC); |
248 | 129 | } |
249 | 130 | |
250 | 131 | nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name); |
132 | sock->fileno = sockfd; | |
251 | 133 | |
252 | sock->fileno = sockfd; | |
253 | 134 | sock->send = socket_send; |
254 | 135 | sock->recv = socket_recv; |
255 | 136 | sock->is_reliable = socket_is_reliable; |
256 | 137 | sock->close = socket_close; |
138 | ||
257 | 139 | return sock; |
258 | 140 | } |
141 | ||
142 | static void | |
143 | socket_close (NiceSocket *sock) | |
144 | { | |
145 | #ifdef G_OS_WIN32 | |
146 | closesocket(sock->fileno); | |
147 | #else | |
148 | close (sock->fileno); | |
149 | #endif | |
150 | } | |
151 | ||
152 | static gint | |
153 | socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) | |
154 | { | |
155 | gint recvd; | |
156 | struct sockaddr_storage sa; | |
157 | socklen_t from_len = sizeof (sa); | |
158 | ||
159 | recvd = recvfrom (sock->fileno, buf, len, 0, (struct sockaddr *) &sa, | |
160 | &from_len); | |
161 | ||
162 | if (recvd > 0) | |
163 | nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); | |
164 | ||
165 | return recvd; | |
166 | } | |
167 | ||
168 | static gboolean | |
169 | socket_send (NiceSocket *sock, const NiceAddress *to, | |
170 | guint len, const gchar *buf) | |
171 | { | |
172 | struct sockaddr_storage sa; | |
173 | ssize_t sent; | |
174 | ||
175 | nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); | |
176 | ||
177 | sent = sendto (sock->fileno, buf, len, 0, (struct sockaddr *) &sa, | |
178 | sa.ss_family == AF_INET? sizeof (struct sockaddr_in) : | |
179 | sizeof(struct sockaddr_in6)); | |
180 | ||
181 | return sent == (ssize_t)len; | |
182 | } | |
183 | ||
184 | static gboolean | |
185 | socket_is_reliable (NiceSocket *sock) | |
186 | { | |
187 | return FALSE; | |
188 | } | |
189 |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * (C) 2008 Nokia Corporation | |
5 | * Contact: Youness Alaoui | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Dafydd Harries, Collabora Ltd. | |
24 | * Youness Alaoui, Collabora Ltd. | |
25 | * Rémi Denis-Courmont, Nokia | |
26 | * Kai Vehmanen | |
27 | * | |
28 | * Alternatively, the contents of this file may be used under the terms of the | |
29 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
30 | * case the provisions of LGPL are applicable instead of those above. If you | |
31 | * wish to allow use of your version of this file only under the terms of the | |
32 | * LGPL and not to allow others to use your version of this file under the | |
33 | * MPL, indicate your decision by deleting the provisions above and replace | |
34 | * them with the notice and other provisions required by the LGPL. If you do | |
35 | * not delete the provisions above, a recipient may use your version of this | |
36 | * file under either the MPL or the LGPL. | |
37 | */ | |
38 | ||
39 | /* | |
40 | * Implementation of UDP socket interface using Berkeley sockets. (See | |
41 | * http://en.wikipedia.org/wiki/Berkeley_sockets.) | |
42 | */ | |
43 | #ifdef HAVE_CONFIG_H | |
44 | # include "config.h" | |
45 | #endif | |
46 | ||
47 | #include <string.h> | |
48 | #include <errno.h> | |
49 | #include <fcntl.h> | |
50 | ||
51 | #include "udp-turn.h" | |
52 | #include "udp-bsd.h" | |
53 | #include "stun/stunagent.h" | |
54 | #include "stun/usages/timer.h" | |
55 | #include "agent-priv.h" | |
56 | ||
57 | typedef struct { | |
58 | StunMessage message; | |
59 | uint8_t buffer[STUN_MAX_MESSAGE_SIZE]; | |
60 | stun_timer_t timer; | |
61 | } TURNMessage; | |
62 | ||
63 | ||
64 | typedef struct { | |
65 | NiceAddress peer; | |
66 | uint16_t channel; | |
67 | } ChannelBinding; | |
68 | ||
69 | typedef struct { | |
70 | NiceAgent *nice; | |
71 | StunAgent agent; | |
72 | GList *channels; | |
73 | GList *pending_bindings; | |
74 | ChannelBinding *current_binding; | |
75 | TURNMessage *current_binding_msg; | |
76 | GSource *tick_source; | |
77 | NiceSocket *base_socket; | |
78 | NiceAddress server_addr; | |
79 | uint8_t *username; | |
80 | size_t username_len; | |
81 | uint8_t *password; | |
82 | size_t password_len; | |
83 | NiceUdpTurnSocketCompatibility compatibility; | |
84 | } turn_priv; | |
85 | ||
86 | static void | |
87 | priv_schedule_tick (turn_priv *priv); | |
88 | ||
89 | static gboolean | |
90 | priv_add_channel_binding (turn_priv *priv, NiceAddress *peer); | |
91 | ||
92 | ||
93 | static void | |
94 | priv_process_pending_bindings (turn_priv *priv) | |
95 | { | |
96 | gboolean ret = FALSE; | |
97 | while (priv->pending_bindings != NULL && ret == FALSE) { | |
98 | NiceAddress *peer = priv->pending_bindings->data; | |
99 | ret = priv_add_channel_binding (priv, peer); | |
100 | priv->pending_bindings = g_list_remove (priv->pending_bindings, peer); | |
101 | nice_address_free (peer); | |
102 | } | |
103 | } | |
104 | ||
105 | static gboolean | |
106 | priv_retransmissions_tick_unlocked (turn_priv *priv) | |
107 | { | |
108 | if (priv->current_binding_msg) { | |
109 | guint timeout = stun_timer_refresh (&priv->current_binding_msg->timer); | |
110 | switch (timeout) { | |
111 | case -1: | |
112 | /* Time out */ | |
113 | g_free (priv->current_binding); | |
114 | priv->current_binding = NULL; | |
115 | g_free (priv->current_binding_msg); | |
116 | priv->current_binding_msg = NULL; | |
117 | priv_process_pending_bindings (priv); | |
118 | break; | |
119 | case 0: | |
120 | /* Retransmit */ | |
121 | nice_socket_send (priv->base_socket, &priv->server_addr, | |
122 | stun_message_length (&priv->current_binding_msg->message), | |
123 | (gchar *)priv->current_binding_msg->buffer); | |
124 | break; | |
125 | default: | |
126 | break; | |
127 | } | |
128 | } | |
129 | ||
130 | priv_schedule_tick (priv); | |
131 | return FALSE; | |
132 | } | |
133 | ||
134 | ||
135 | static gboolean | |
136 | priv_retransmissions_tick (gpointer pointer) | |
137 | { | |
138 | turn_priv *priv = pointer; | |
139 | gboolean ret; | |
140 | ||
141 | g_static_rec_mutex_lock (&priv->nice->mutex); | |
142 | ret = priv_retransmissions_tick_unlocked (priv); | |
143 | g_static_rec_mutex_unlock (&priv->nice->mutex); | |
144 | ||
145 | return ret; | |
146 | } | |
147 | ||
148 | static void | |
149 | priv_schedule_tick (turn_priv *priv) | |
150 | { | |
151 | if (priv->tick_source != NULL) { | |
152 | g_source_destroy (priv->tick_source); | |
153 | g_source_unref (priv->tick_source); | |
154 | priv->tick_source = NULL; | |
155 | } | |
156 | ||
157 | if (priv->current_binding_msg) { | |
158 | guint timeout = stun_timer_remainder (&priv->current_binding_msg->timer); | |
159 | if (timeout > 0) { | |
160 | priv->tick_source = agent_timeout_add_with_context (priv->nice, timeout, | |
161 | priv_retransmissions_tick, priv); | |
162 | } else { | |
163 | priv_retransmissions_tick_unlocked (priv); | |
164 | } | |
165 | } | |
166 | } | |
167 | ||
168 | static void | |
169 | priv_send_turn_message (turn_priv *priv, TURNMessage *msg) | |
170 | { | |
171 | size_t stun_len = stun_message_length (&msg->message); | |
172 | ||
173 | if (priv->current_binding_msg) { | |
174 | g_free (priv->current_binding_msg); | |
175 | priv->current_binding_msg = NULL; | |
176 | } | |
177 | ||
178 | nice_socket_send (priv->base_socket, &priv->server_addr, | |
179 | stun_len, (gchar *)msg->buffer); | |
180 | ||
181 | if (nice_socket_is_reliable (priv->base_socket)) { | |
182 | stun_timer_start_reliable (&msg->timer); | |
183 | } else { | |
184 | stun_timer_start (&msg->timer); | |
185 | } | |
186 | ||
187 | priv->current_binding_msg = msg; | |
188 | priv_schedule_tick (priv); | |
189 | } | |
190 | ||
191 | static gboolean | |
192 | priv_send_channel_bind (turn_priv *priv, StunMessage *resp, | |
193 | uint16_t channel, NiceAddress *peer) { | |
194 | uint32_t channel_attr = channel << 16; | |
195 | size_t stun_len; | |
196 | struct sockaddr_storage sa; | |
197 | TURNMessage *msg = g_new0 (TURNMessage, 1); | |
198 | ||
199 | nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa); | |
200 | ||
201 | if (!stun_agent_init_request (&priv->agent, &msg->message, | |
202 | msg->buffer, sizeof(msg->buffer), STUN_CHANNELBIND)) { | |
203 | g_free (msg); | |
204 | return FALSE; | |
205 | } | |
206 | ||
207 | if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_CHANNEL_NUMBER, | |
208 | channel_attr) != 0) { | |
209 | g_free (msg); | |
210 | return FALSE; | |
211 | } | |
212 | ||
213 | if (stun_message_append_xor_addr (&msg->message, STUN_ATTRIBUTE_PEER_ADDRESS, | |
214 | (struct sockaddr *)&sa, sizeof(sa)) != 0) { | |
215 | g_free (msg); | |
216 | return FALSE; | |
217 | } | |
218 | ||
219 | if (priv->username != NULL && priv->username_len > 0) { | |
220 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME, | |
221 | priv->username, priv->username_len) != 0) { | |
222 | g_free (msg); | |
223 | return FALSE; | |
224 | } | |
225 | } | |
226 | ||
227 | if (resp) { | |
228 | uint8_t *realm; | |
229 | uint8_t *nonce; | |
230 | uint16_t len; | |
231 | ||
232 | realm = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_REALM, &len); | |
233 | if (realm != NULL) { | |
234 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM, | |
235 | realm, len) != 0) { | |
236 | g_free (msg); | |
237 | return 0; | |
238 | } | |
239 | } | |
240 | nonce = (uint8_t *) stun_message_find (resp, STUN_ATTRIBUTE_NONCE, &len); | |
241 | if (nonce != NULL) { | |
242 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE, | |
243 | nonce, len) != 0) { | |
244 | g_free (msg); | |
245 | return 0; | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
250 | stun_len = stun_agent_finish_message (&priv->agent, &msg->message, | |
251 | priv->password, priv->password_len); | |
252 | ||
253 | if (stun_len > 0) { | |
254 | priv_send_turn_message (priv, msg); | |
255 | return TRUE; | |
256 | } | |
257 | ||
258 | g_free (msg); | |
259 | return FALSE; | |
260 | } | |
261 | ||
262 | static gboolean | |
263 | priv_add_channel_binding (turn_priv *priv, NiceAddress *peer) | |
264 | { | |
265 | size_t stun_len; | |
266 | struct sockaddr_storage sa; | |
267 | ||
268 | nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa); | |
269 | ||
270 | if (priv->current_binding) { | |
271 | NiceAddress * pending= nice_address_new (); | |
272 | *pending = *peer; | |
273 | priv->pending_bindings = g_list_append (priv->pending_bindings, pending); | |
274 | return FALSE; | |
275 | } | |
276 | ||
277 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
278 | uint16_t channel = 0x4000; | |
279 | GList *i = priv->channels; | |
280 | for (; i; i = i->next) { | |
281 | ChannelBinding *b = i->data; | |
282 | if (channel == b->channel) { | |
283 | i = priv->channels; | |
284 | channel++; | |
285 | continue; | |
286 | } | |
287 | } | |
288 | ||
289 | if (channel >= 0x4000 && channel < 0xffff) { | |
290 | gboolean ret = priv_send_channel_bind (priv, NULL, channel, peer); | |
291 | if (ret) { | |
292 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
293 | priv->current_binding->channel = channel; | |
294 | priv->current_binding->peer = *peer; | |
295 | } | |
296 | return ret; | |
297 | } | |
298 | return FALSE; | |
299 | } else if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN) { | |
300 | TURNMessage *msg = g_new0 (TURNMessage, 1); | |
301 | if (!stun_agent_init_request (&priv->agent, &msg->message, | |
302 | msg->buffer, sizeof(msg->buffer), STUN_OLD_SET_ACTIVE_DST)) { | |
303 | g_free (msg); | |
304 | return FALSE; | |
305 | } | |
306 | ||
307 | if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
308 | TURN_MAGIC_COOKIE) != 0) { | |
309 | g_free (msg); | |
310 | return FALSE; | |
311 | } | |
312 | ||
313 | if (priv->username != NULL && priv->username_len > 0) { | |
314 | if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME, | |
315 | priv->username, priv->username_len) != 0) { | |
316 | g_free (msg); | |
317 | return FALSE; | |
318 | } | |
319 | } | |
320 | ||
321 | if (stun_message_append_addr (&msg->message, | |
322 | STUN_ATTRIBUTE_DESTINATION_ADDRESS, | |
323 | (struct sockaddr *)&sa, sizeof(sa)) != 0) { | |
324 | g_free (msg); | |
325 | return FALSE; | |
326 | } | |
327 | ||
328 | stun_len = stun_agent_finish_message (&priv->agent, &msg->message, | |
329 | priv->password, priv->password_len); | |
330 | ||
331 | if (stun_len > 0) { | |
332 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
333 | priv->current_binding->channel = 0; | |
334 | priv->current_binding->peer = *peer; | |
335 | priv_send_turn_message (priv, msg); | |
336 | return TRUE; | |
337 | } | |
338 | g_free (msg); | |
339 | return FALSE; | |
340 | } else if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
341 | priv->current_binding = g_new0 (ChannelBinding, 1); | |
342 | priv->current_binding->channel = 0; | |
343 | priv->current_binding->peer = *peer; | |
344 | return TRUE; | |
345 | } else { | |
346 | return FALSE; | |
347 | } | |
348 | ||
349 | return FALSE; | |
350 | } | |
351 | ||
352 | gboolean | |
353 | nice_udp_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer) | |
354 | { | |
355 | turn_priv *priv = (turn_priv *) sock->priv; | |
356 | return priv_add_channel_binding (priv, peer); | |
357 | } | |
358 | ||
359 | ||
360 | gint | |
361 | nice_udp_turn_socket_parse_recv ( | |
362 | NiceSocket *sock, | |
363 | NiceSocket **from_sock, | |
364 | NiceAddress *from, | |
365 | guint len, | |
366 | gchar *buf, | |
367 | NiceAddress *recv_from, | |
368 | gchar *recv_buf, | |
369 | guint recv_len) | |
370 | { | |
371 | ||
372 | turn_priv *priv = (turn_priv *) sock->priv; | |
373 | StunValidationStatus valid; | |
374 | StunMessage msg; | |
375 | struct sockaddr_storage sa; | |
376 | socklen_t from_len = sizeof (sa); | |
377 | GList *i = priv->channels; | |
378 | ChannelBinding *binding = NULL; | |
379 | ||
380 | if (nice_address_equal (&priv->server_addr, recv_from)) { | |
381 | valid = stun_agent_validate (&priv->agent, &msg, | |
382 | (uint8_t *) recv_buf, (size_t) recv_len, NULL, NULL); | |
383 | ||
384 | if (valid == STUN_VALIDATION_SUCCESS) { | |
385 | if (priv->compatibility != NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
386 | uint32_t cookie; | |
387 | if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
388 | &cookie) != 0) | |
389 | goto recv; | |
390 | if (cookie != TURN_MAGIC_COOKIE) | |
391 | goto recv; | |
392 | } | |
393 | ||
394 | if (stun_message_get_method (&msg) == STUN_SEND) { | |
395 | if (stun_message_get_class (&msg) == STUN_RESPONSE && | |
396 | priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
397 | uint32_t opts = 0; | |
398 | if (stun_message_find32 (&msg, STUN_ATTRIBUTE_OPTIONS, &opts) == 0 && | |
399 | opts & 0x1) | |
400 | goto msn_google_lock; | |
401 | } | |
402 | return 0; | |
403 | } else if (stun_message_get_method (&msg) == STUN_OLD_SET_ACTIVE_DST) { | |
404 | stun_transid_t request_id; | |
405 | stun_transid_t response_id; | |
406 | if (priv->current_binding && priv->current_binding_msg) { | |
407 | stun_message_id (&msg, response_id); | |
408 | stun_message_id (&priv->current_binding_msg->message, request_id); | |
409 | if (memcmp (request_id, response_id, sizeof(stun_transid_t)) == 0) { | |
410 | g_free (priv->current_binding_msg); | |
411 | priv->current_binding_msg = NULL; | |
412 | ||
413 | if (stun_message_get_class (&msg) == STUN_RESPONSE && | |
414 | priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN) { | |
415 | goto msn_google_lock; | |
416 | } else { | |
417 | g_free (priv->current_binding); | |
418 | priv->current_binding = NULL; | |
419 | } | |
420 | } | |
421 | } | |
422 | ||
423 | return 0; | |
424 | } else if (stun_message_get_method (&msg) == STUN_CHANNELBIND) { | |
425 | stun_transid_t request_id; | |
426 | stun_transid_t response_id; | |
427 | if (priv->current_binding && priv->current_binding_msg) { | |
428 | stun_message_id (&msg, response_id); | |
429 | stun_message_id (&priv->current_binding_msg->message, request_id); | |
430 | if (memcmp (request_id, response_id, sizeof(stun_transid_t)) == 0) { | |
431 | if (stun_message_get_class (&msg) == STUN_ERROR) { | |
432 | int code = -1; | |
433 | uint8_t *sent_realm = NULL; | |
434 | uint8_t *recv_realm = NULL; | |
435 | uint16_t sent_realm_len = 0; | |
436 | uint16_t recv_realm_len = 0; | |
437 | ||
438 | sent_realm = (uint8_t *) stun_message_find ( | |
439 | &priv->current_binding_msg->message, | |
440 | STUN_ATTRIBUTE_REALM, &sent_realm_len); | |
441 | recv_realm = (uint8_t *) stun_message_find (&msg, | |
442 | STUN_ATTRIBUTE_REALM, &recv_realm_len); | |
443 | ||
444 | /* check for unauthorized error response */ | |
445 | if (stun_message_find_error (&msg, &code) == 0 && | |
446 | (code == 438 || (code == 401 && | |
447 | !(recv_realm != NULL && | |
448 | recv_realm_len > 0 && | |
449 | recv_realm_len == sent_realm_len && | |
450 | sent_realm != NULL && | |
451 | memcmp (sent_realm, recv_realm, sent_realm_len) == 0)))) { | |
452 | g_free (priv->current_binding_msg); | |
453 | priv->current_binding_msg = NULL; | |
454 | if (priv->current_binding) { | |
455 | priv_send_channel_bind (priv, &msg, | |
456 | priv->current_binding->channel, | |
457 | &priv->current_binding->peer); | |
458 | } | |
459 | } else { | |
460 | g_free (priv->current_binding); | |
461 | priv->current_binding = NULL; | |
462 | g_free (priv->current_binding_msg); | |
463 | priv->current_binding_msg = NULL; | |
464 | priv_process_pending_bindings (priv); | |
465 | } | |
466 | } else if (stun_message_get_class (&msg) == STUN_RESPONSE) { | |
467 | g_free (priv->current_binding_msg); | |
468 | priv->current_binding_msg = NULL; | |
469 | if (priv->current_binding) { | |
470 | priv->channels = g_list_append (priv->channels, | |
471 | priv->current_binding); | |
472 | priv->current_binding = NULL; | |
473 | } | |
474 | priv_process_pending_bindings (priv); | |
475 | } | |
476 | } | |
477 | } | |
478 | return 0; | |
479 | } else if (stun_message_get_class (&msg) == STUN_INDICATION && | |
480 | stun_message_get_method (&msg) == STUN_IND_DATA) { | |
481 | uint16_t data_len; | |
482 | uint8_t *data; | |
483 | ||
484 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
485 | if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS, | |
486 | (struct sockaddr *)&sa, &from_len) != 0) | |
487 | goto recv; | |
488 | } else { | |
489 | if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS, | |
490 | (struct sockaddr *)&sa, &from_len) != 0) | |
491 | goto recv; | |
492 | } | |
493 | ||
494 | data = (uint8_t *) stun_message_find (&msg, STUN_ATTRIBUTE_DATA, | |
495 | &data_len); | |
496 | ||
497 | if (data == NULL) | |
498 | goto recv; | |
499 | ||
500 | nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); | |
501 | ||
502 | *from_sock = sock; | |
503 | memmove (buf, data, len > data_len ? data_len : len); | |
504 | return len > data_len ? data_len : len; | |
505 | } else { | |
506 | goto recv; | |
507 | } | |
508 | } | |
509 | } | |
510 | ||
511 | recv: | |
512 | for (i = priv->channels; i; i = i->next) { | |
513 | ChannelBinding *b = i->data; | |
514 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
515 | if (b->channel == ntohs(((uint16_t *)recv_buf)[0])) { | |
516 | recv_len = ntohs (((uint16_t *)recv_buf)[1]); | |
517 | recv_buf += sizeof(uint32_t); | |
518 | binding = b; | |
519 | break; | |
520 | } | |
521 | } else { | |
522 | binding = b; | |
523 | break; | |
524 | } | |
525 | } | |
526 | ||
527 | if (binding) { | |
528 | *from = binding->peer; | |
529 | *from_sock = sock; | |
530 | } else { | |
531 | *from = *recv_from; | |
532 | } | |
533 | ||
534 | memmove (buf, recv_buf, len > recv_len ? recv_len : len); | |
535 | return len > recv_len ? recv_len : len; | |
536 | ||
537 | msn_google_lock: | |
538 | ||
539 | if (priv->current_binding) { | |
540 | GList *i = priv->channels; | |
541 | for (; i; i = i->next) { | |
542 | ChannelBinding *b = i->data; | |
543 | g_free (b); | |
544 | } | |
545 | g_list_free (priv->channels); | |
546 | priv->channels = g_list_append (NULL, priv->current_binding); | |
547 | priv->current_binding = NULL; | |
548 | priv_process_pending_bindings (priv); | |
549 | } | |
550 | ||
551 | return 0; | |
552 | } | |
553 | ||
554 | static gint | |
555 | socket_recv ( | |
556 | NiceSocket *sock, | |
557 | NiceAddress *from, | |
558 | guint len, | |
559 | gchar *buf) | |
560 | { | |
561 | turn_priv *priv = (turn_priv *) sock->priv; | |
562 | uint8_t recv_buf[STUN_MAX_MESSAGE_SIZE]; | |
563 | gint recv_len; | |
564 | NiceAddress recv_from; | |
565 | NiceSocket *dummy;; | |
566 | ||
567 | recv_len = nice_socket_recv (priv->base_socket, &recv_from, | |
568 | sizeof(recv_buf), (gchar *) recv_buf); | |
569 | ||
570 | return nice_udp_turn_socket_parse_recv (sock, &dummy, from, len, buf, | |
571 | &recv_from, (gchar *) recv_buf, (guint) recv_len); | |
572 | } | |
573 | ||
574 | static gboolean | |
575 | socket_send ( | |
576 | NiceSocket *sock, | |
577 | const NiceAddress *to, | |
578 | guint len, | |
579 | const gchar *buf) | |
580 | { | |
581 | turn_priv *priv = (turn_priv *) sock->priv; | |
582 | StunMessage msg; | |
583 | uint8_t buffer[STUN_MAX_MESSAGE_SIZE]; | |
584 | size_t msg_len; | |
585 | struct sockaddr_storage sa; | |
586 | GList *i = priv->channels; | |
587 | ChannelBinding *binding = NULL; | |
588 | ||
589 | for (; i; i = i->next) { | |
590 | ChannelBinding *b = i->data; | |
591 | if (nice_address_equal (&b->peer, to)) { | |
592 | binding = b; | |
593 | break; | |
594 | } | |
595 | } | |
596 | ||
597 | nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); | |
598 | ||
599 | if (binding) { | |
600 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9 && | |
601 | len + sizeof(uint32_t) <= sizeof(buffer)) { | |
602 | uint16_t len16 = htons ((uint16_t) len); | |
603 | uint16_t channel16 = htons (binding->channel); | |
604 | memcpy (buffer, &channel16, sizeof(uint16_t)); | |
605 | memcpy (buffer + sizeof(uint16_t), &len16,sizeof(uint16_t)); | |
606 | memcpy (buffer + sizeof(uint32_t), buf, len); | |
607 | msg_len = len + sizeof(uint32_t); | |
608 | } else { | |
609 | return nice_socket_send (priv->base_socket, &priv->server_addr, len, buf); | |
610 | } | |
611 | } else { | |
612 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
613 | if (!stun_agent_init_indication (&priv->agent, &msg, | |
614 | buffer, sizeof(buffer), STUN_IND_SEND)) | |
615 | goto send; | |
616 | if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_PEER_ADDRESS, | |
617 | (struct sockaddr *)&sa, sizeof(sa)) != 0) | |
618 | goto send; | |
619 | } else { | |
620 | if (!stun_agent_init_request (&priv->agent, &msg, | |
621 | buffer, sizeof(buffer), STUN_SEND)) | |
622 | goto send; | |
623 | ||
624 | if (stun_message_append32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE, | |
625 | TURN_MAGIC_COOKIE) != 0) | |
626 | goto send; | |
627 | if (priv->username != NULL && priv->username_len > 0) { | |
628 | if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_USERNAME, | |
629 | priv->username, priv->username_len) != 0) | |
630 | goto send; | |
631 | } | |
632 | if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_DESTINATION_ADDRESS, | |
633 | (struct sockaddr *)&sa, sizeof(sa)) != 0) | |
634 | goto send; | |
635 | ||
636 | if (priv->compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE && | |
637 | priv->current_binding && | |
638 | nice_address_equal (&priv->current_binding->peer, to)) { | |
639 | stun_message_append32 (&msg, STUN_ATTRIBUTE_OPTIONS, 1); | |
640 | } | |
641 | } | |
642 | ||
643 | if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_DATA, buf, len) != 0) | |
644 | goto send; | |
645 | ||
646 | msg_len = stun_agent_finish_message (&priv->agent, &msg, | |
647 | priv->password, priv->password_len); | |
648 | } | |
649 | ||
650 | if (msg_len > 0) { | |
651 | return nice_socket_send (priv->base_socket, &priv->server_addr, | |
652 | msg_len, (gchar *)buffer); | |
653 | } | |
654 | send: | |
655 | return nice_socket_send (priv->base_socket, to, len, buf); | |
656 | } | |
657 | ||
658 | static gboolean | |
659 | socket_is_reliable (NiceSocket *sock) | |
660 | { | |
661 | turn_priv *priv = (turn_priv *) sock->priv; | |
662 | return nice_socket_is_reliable (priv->base_socket); | |
663 | } | |
664 | ||
665 | static void | |
666 | socket_close (NiceSocket *sock) | |
667 | { | |
668 | turn_priv *priv = (turn_priv *) sock->priv; | |
669 | GList *i = NULL; | |
670 | for (i = priv->channels; i; i = i->next) { | |
671 | ChannelBinding *b = i->data; | |
672 | g_free (b); | |
673 | } | |
674 | g_list_free (priv->channels); | |
675 | ||
676 | for (i = priv->pending_bindings; i; i = i->next) { | |
677 | ChannelBinding *b = i->data; | |
678 | g_free (b); | |
679 | } | |
680 | g_list_free (priv->pending_bindings); | |
681 | ||
682 | if (priv->tick_source != NULL) { | |
683 | g_source_destroy (priv->tick_source); | |
684 | g_source_unref (priv->tick_source); | |
685 | priv->tick_source = NULL; | |
686 | } | |
687 | ||
688 | g_free (priv->current_binding); | |
689 | g_free (priv->current_binding_msg); | |
690 | g_free (priv->username); | |
691 | g_free (priv->password); | |
692 | g_free (priv); | |
693 | } | |
694 | ||
695 | ||
696 | NiceSocket * | |
697 | nice_udp_turn_socket_new ( | |
698 | NiceAgent *agent, | |
699 | NiceAddress *addr, | |
700 | NiceSocket *base_socket, | |
701 | NiceAddress *server_addr, | |
702 | gchar *username, | |
703 | gchar *password, | |
704 | NiceUdpTurnSocketCompatibility compatibility) | |
705 | { | |
706 | turn_priv *priv = g_new0 (turn_priv, 1); | |
707 | NiceSocket *sock = g_slice_new0 (NiceSocket); | |
708 | ||
709 | if (!sock) { | |
710 | return NULL; | |
711 | } | |
712 | ||
713 | if (compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9) { | |
714 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
715 | STUN_COMPATIBILITY_RFC5389, | |
716 | STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS); | |
717 | } else if (compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN) { | |
718 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
719 | STUN_COMPATIBILITY_RFC3489, | |
720 | STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | | |
721 | STUN_AGENT_USAGE_NO_INDICATION_AUTH); | |
722 | } else if (compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
723 | stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES, | |
724 | STUN_COMPATIBILITY_RFC3489, | |
725 | STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | | |
726 | STUN_AGENT_USAGE_IGNORE_CREDENTIALS); | |
727 | } | |
728 | ||
729 | priv->nice = agent; | |
730 | priv->channels = NULL; | |
731 | priv->current_binding = NULL; | |
732 | priv->base_socket = base_socket; | |
733 | ||
734 | if (compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN) { | |
735 | priv->username = g_base64_decode (username, &priv->username_len); | |
736 | priv->password = g_base64_decode (password, &priv->password_len); | |
737 | } else { | |
738 | priv->username = (uint8_t *)g_strdup (username); | |
739 | priv->username_len = (size_t) strlen (username); | |
740 | if (compatibility == NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE) { | |
741 | priv->password = NULL; | |
742 | priv->password_len = 0; | |
743 | } else { | |
744 | priv->password = (uint8_t *)g_strdup (password); | |
745 | priv->password_len = (size_t) strlen (password); | |
746 | } | |
747 | } | |
748 | priv->server_addr = *server_addr; | |
749 | priv->compatibility = compatibility; | |
750 | sock->addr = *addr; | |
751 | sock->fileno = base_socket->fileno; | |
752 | sock->send = socket_send; | |
753 | sock->recv = socket_recv; | |
754 | sock->is_reliable = socket_is_reliable; | |
755 | sock->close = socket_close; | |
756 | sock->priv = (void *) priv; | |
757 | return sock; | |
758 | } |
0 | /* | |
1 | * This file is part of the Nice GLib ICE library. | |
2 | * | |
3 | * (C) 2008 Collabora Ltd. | |
4 | * (C) 2008 Nokia Corporation | |
5 | * Contact: Youness Alaoui | |
6 | * | |
7 | * The contents of this file are subject to the Mozilla Public License Version | |
8 | * 1.1 (the "License"); you may not use this file except in compliance with | |
9 | * the License. You may obtain a copy of the License at | |
10 | * http://www.mozilla.org/MPL/ | |
11 | * | |
12 | * Software distributed under the License is distributed on an "AS IS" basis, | |
13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
14 | * for the specific language governing rights and limitations under the | |
15 | * License. | |
16 | * | |
17 | * The Original Code is the Nice GLib ICE library. | |
18 | * | |
19 | * The Initial Developers of the Original Code are Collabora Ltd and Nokia | |
20 | * Corporation. All Rights Reserved. | |
21 | * | |
22 | * Contributors: | |
23 | * Dafydd Harries, Collabora Ltd. | |
24 | * Youness Alaoui, Collabora Ltd. | |
25 | * | |
26 | * Alternatively, the contents of this file may be used under the terms of the | |
27 | * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which | |
28 | * case the provisions of LGPL are applicable instead of those above. If you | |
29 | * wish to allow use of your version of this file only under the terms of the | |
30 | * LGPL and not to allow others to use your version of this file under the | |
31 | * MPL, indicate your decision by deleting the provisions above and replace | |
32 | * them with the notice and other provisions required by the LGPL. If you do | |
33 | * not delete the provisions above, a recipient may use your version of this | |
34 | * file under either the MPL or the LGPL. | |
35 | */ | |
36 | ||
37 | #ifndef _UDP_TURN_H | |
38 | #define _UDP_TURN_H | |
39 | ||
40 | ||
41 | typedef enum { | |
42 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_DRAFT9, | |
43 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_GOOGLE, | |
44 | NICE_UDP_TURN_SOCKET_COMPATIBILITY_MSN, | |
45 | } NiceUdpTurnSocketCompatibility; | |
46 | ||
47 | #include "socket.h" | |
48 | #include "agent.h" | |
49 | ||
50 | ||
51 | G_BEGIN_DECLS | |
52 | ||
53 | gint | |
54 | nice_udp_turn_socket_parse_recv ( | |
55 | NiceSocket *sock, | |
56 | NiceSocket **from_sock, | |
57 | NiceAddress *from, | |
58 | guint len, | |
59 | gchar *buf, | |
60 | NiceAddress *recv_from, | |
61 | gchar *recv_buf, | |
62 | guint recv_len); | |
63 | ||
64 | gboolean | |
65 | nice_udp_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer); | |
66 | ||
67 | NiceSocket * | |
68 | nice_udp_turn_socket_new ( | |
69 | NiceAgent *agent, | |
70 | NiceAddress *addr, | |
71 | NiceSocket *udp_socket, | |
72 | NiceAddress *server_addr, | |
73 | gchar *username, | |
74 | gchar *password, | |
75 | NiceUdpTurnSocketCompatibility compatibility); | |
76 | ||
77 | ||
78 | G_END_DECLS | |
79 | ||
80 | #endif /* _UDP_TURN_H */ | |
81 |
134 | 134 | NICE_LT_LDFLAGS = @NICE_LT_LDFLAGS@ |
135 | 135 | NM = @NM@ |
136 | 136 | NMEDIT = @NMEDIT@ |
137 | OBJDUMP = @OBJDUMP@ | |
137 | 138 | OBJEXT = @OBJEXT@ |
138 | 139 | OTOOL = @OTOOL@ |
139 | 140 | OTOOL64 = @OTOOL64@ |